nodeipc: use unbuffered read if we know the message size

Summary:
This avoids over reading which might drop special messages (like file descriptors)
from sendmsg(). Buffered reader might turn those special messages into regular
messages and will lose the file descriptors.

Reviewed By: muirdm

Differential Revision: D46811158

fbshipit-source-id: 2294c5c2b132c25c21950f26e9f0d44094743fe0
This commit is contained in:
Jun Wu 2023-06-21 14:49:59 -07:00 committed by Facebook GitHub Bot
parent c372790323
commit 3a4d26c5af

View File

@ -192,10 +192,22 @@ impl NodeIpc {
fn recv_line(&self) -> anyhow::Result<Option<String>> { fn recv_line(&self) -> anyhow::Result<Option<String>> {
let mut r = self.r.lock().unwrap(); let mut r = self.r.lock().unwrap();
if cfg!(windows) && self.libuv_compat { if cfg!(windows) && self.libuv_compat {
// libuv adds frame headers on Windows. Skip them. // Use unbuffered read to avoid over reading.
assert!(r.buffer().is_empty());
let r = r.get_mut();
let mut libuv_pipe_frame_header = [0u8; std::mem::size_of::<UvPipeWin32FrameHeader>()]; let mut libuv_pipe_frame_header = [0u8; std::mem::size_of::<UvPipeWin32FrameHeader>()];
r.read_exact(&mut libuv_pipe_frame_header) r.read_exact(&mut libuv_pipe_frame_header)
.context("in NodeIpc::recv, when reading frame header")?; .context("in NodeIpc::recv, when reading frame header")?;
let header: UvPipeWin32FrameHeader =
unsafe { std::mem::transmute(libuv_pipe_frame_header) };
let size = header.data_length as usize;
if size == 0 {
return Ok(None);
}
let mut buf = vec![0u8; size];
r.read_exact(&mut buf).context("in NodeIpc::recv")?;
let line = String::from_utf8(buf).context("in NodeIpc::recv")?;
return Ok(Some(line));
} }
let mut line = String::new(); let mut line = String::new();
let n = r.read_line(&mut line).context("in NodeIpc::recv")?; let n = r.read_line(&mut line).context("in NodeIpc::recv")?;