diff --git a/CHANGES.md b/CHANGES.md index 7f3473d9c89..b3ad66516aa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ Unreleased ---------- +- RPC: Ignore SIGPIPE when clients suddenly disconnect on OSX (#7299, partially + fixes #6879, @rgrinberg) + - Always clean up the UI on exit. (#7271, fixes #7142 @rgrinberg) - Bootstrap: remove reliance on shell. Previously, we'd use the shell to get diff --git a/src/csexp_rpc/csexp_rpc.ml b/src/csexp_rpc/csexp_rpc.ml index 3ccbb770074..8fa328dceb7 100644 --- a/src/csexp_rpc/csexp_rpc.ml +++ b/src/csexp_rpc/csexp_rpc.ml @@ -61,9 +61,11 @@ module Socket = struct let bind fd sock = Unix.bind fd sock end - module Mac : Unix_socket = struct + module Mac = struct external pthread_chdir : string -> unit = "dune_pthread_chdir" [@@noalloc] + external set_nosigpipe : Unix.file_descr -> unit = "dune_set_nosigpipe" + let with_chdir fd ~socket ~f = let old = Sys.getcwd () in let dir = Filename.dirname socket in @@ -114,6 +116,8 @@ module Socket = struct let bind = make ~original:U.bind ~backup:Sel.bind let connect = make ~original:U.connect ~backup:Sel.connect + + let maybe_set_nosigpipe fd = if is_osx () then Mac.set_nosigpipe fd end let debug = Option.is_some (Env.get Env.initial "DUNE_RPC_DEBUG") @@ -328,6 +332,7 @@ module Server = struct Worker.task async ~f:(fun () -> Transport.accept transport |> Option.map ~f:(fun client -> + Socket.maybe_set_nosigpipe fd; let in_ = Unix.in_channel_of_descr client in let out = Unix.out_channel_of_descr client in (in_, out))) diff --git a/src/csexp_rpc/pthread_chdir_stubs.c b/src/csexp_rpc/pthread_chdir_stubs.c index 81609c4e732..5110b26557f 100644 --- a/src/csexp_rpc/pthread_chdir_stubs.c +++ b/src/csexp_rpc/pthread_chdir_stubs.c @@ -10,6 +10,8 @@ #if defined(__APPLE__) #include +#include +#include #include #include @@ -19,7 +21,6 @@ CAMLprim value dune_pthread_chdir_is_osx(value unit) CAMLreturn(Val_true); } - #ifndef SYS___pthread_chdir # define SYS___pthread_chdir 348 #endif @@ -40,8 +41,23 @@ CAMLprim value dune_pthread_chdir(value dir) { CAMLreturn (Val_unit); } +CAMLprim value dune_set_nosigpipe(value v_socket) { + CAMLparam1(v_socket); + int socket = Int_val(v_socket); + int opt = 1; + int ret = setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(int)); + if (ret < 0) { + uerror("setsockopt", Nothing); + } + CAMLreturn(Val_unit); +} + #else +CAMLprim value dune_set_nosigpipe(value v_socket) { + caml_invalid_argument("only implemented on macos"); +} + CAMLprim value dune_pthread_chdir_is_osx(value unit) { CAMLparam1(unit);