mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
nodeipc: avoid closing underlying fd multiple times
Summary: The `FileDescriptor` type will close the underlying fd on drop. In our use-cases `r` and `w` refer to the same fd so we only need to close it once. Note the reason we use separate `Mutex`es for r and w is that we want `recv()` and `send()` running from different threads to not block by each other. Reviewed By: zzl0 Differential Revision: D46885308 fbshipit-source-id: b2a5644251ac4773581a995ae8c3d955b0b36861
This commit is contained in:
parent
8a46d73b6e
commit
d9334ee302
@ -12,6 +12,7 @@ use std::io;
|
|||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
@ -39,7 +40,9 @@ pub type LibcFd = libc::c_int;
|
|||||||
pub struct NodeIpc {
|
pub struct NodeIpc {
|
||||||
// Mutex is used so the static singleton is easier to use
|
// Mutex is used so the static singleton is easier to use
|
||||||
// (send and recv do not take &mut self).
|
// (send and recv do not take &mut self).
|
||||||
pub(crate) w: Mutex<FileDescriptor>,
|
// `r` and `w` share a same file descriptor. `FileDescriptor` closes the underlying
|
||||||
|
// fd on drop. Use `ManuallyDrop` to avoid duplicated closing.
|
||||||
|
pub(crate) w: Mutex<ManuallyDrop<FileDescriptor>>,
|
||||||
pub(crate) r: Mutex<io::BufReader<FileDescriptor>>,
|
pub(crate) r: Mutex<io::BufReader<FileDescriptor>>,
|
||||||
// Whether compatible with libuv.
|
// Whether compatible with libuv.
|
||||||
// If true, on Windows, we'll add extra frame headers per message.
|
// If true, on Windows, we'll add extra frame headers per message.
|
||||||
@ -90,6 +93,10 @@ impl NodeIpc {
|
|||||||
|
|
||||||
/// Initialize `NodeIpc` from a OS raw file descriptor.
|
/// Initialize `NodeIpc` from a OS raw file descriptor.
|
||||||
/// The `RawFileDescriptor` is libc fd on POSIX, or `HANDLE` on Windows.
|
/// The `RawFileDescriptor` is libc fd on POSIX, or `HANDLE` on Windows.
|
||||||
|
///
|
||||||
|
/// Note: `NodeIpc` will close the underlying file descriptor on drop.
|
||||||
|
/// So the callsite needs to "forget" the file descriptor if it does not
|
||||||
|
/// want to close it twice.
|
||||||
pub fn from_raw_file_descriptor(
|
pub fn from_raw_file_descriptor(
|
||||||
raw_file_descriptor: RawFileDescriptor,
|
raw_file_descriptor: RawFileDescriptor,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
@ -97,7 +104,7 @@ impl NodeIpc {
|
|||||||
let fd = get_fd();
|
let fd = get_fd();
|
||||||
|
|
||||||
let r = Mutex::new(io::BufReader::new(fd));
|
let r = Mutex::new(io::BufReader::new(fd));
|
||||||
let w = Mutex::new(get_fd());
|
let w = Mutex::new(ManuallyDrop::new(get_fd()));
|
||||||
let libuv_compat = false;
|
let libuv_compat = false;
|
||||||
let ipc = Self { r, w, libuv_compat };
|
let ipc = Self { r, w, libuv_compat };
|
||||||
Ok(ipc)
|
Ok(ipc)
|
||||||
|
Loading…
Reference in New Issue
Block a user