Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/rpc/csexp_rpc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ module Socket = struct

module Mac = struct
external pthread_chdir : string -> unit = "dune_pthread_chdir"
external reset_pthread_cwd : unit -> unit = "dune_reset_pthread_cwd"
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
let sock = Filename.basename socket in
pthread_chdir dir;
Exn.protectx (Unix.ADDR_UNIX sock) ~f:(f fd) ~finally:(fun _ -> pthread_chdir old)
Exn.protectx (Unix.ADDR_UNIX sock) ~f:(f fd) ~finally:(fun _ ->
reset_pthread_cwd ())
;;

let connect fd ~socket : unit =
Expand Down
24 changes: 24 additions & 0 deletions src/rpc/csexp_rpc_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ CAMLprim value dune_pthread_chdir_is_osx(value unit) {
#ifndef SYS___pthread_chdir
#define SYS___pthread_chdir 348
#endif
#ifndef SYS___pthread_fchdir
#define SYS___pthread_fchdir 349
#endif

static int __pthread_chdir(const char *path) {
#pragma clang diagnostic push
Expand All @@ -31,6 +34,13 @@ static int __pthread_chdir(const char *path) {
#pragma clang diagnostic pop
}

static int __pthread_fchdir(int fd) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
return syscall(SYS___pthread_fchdir, fd);
#pragma clang diagnostic pop
}

CAMLprim value dune_pthread_chdir(value dir) {
CAMLparam1(dir);
if (__pthread_chdir(String_val(dir))) {
Expand All @@ -39,6 +49,14 @@ CAMLprim value dune_pthread_chdir(value dir) {
CAMLreturn(Val_unit);
}

CAMLprim value dune_reset_pthread_cwd(value unit) {
CAMLparam1(unit);
if (__pthread_fchdir(-1)) {
uerror("__pthread_fchdir", Nothing);
}
CAMLreturn(Val_unit);
}

CAMLprim value dune_set_nosigpipe(value v_socket) {
CAMLparam1(v_socket);
int socket = Int_val(v_socket);
Expand Down Expand Up @@ -67,6 +85,12 @@ CAMLprim value dune_pthread_chdir(value unit) {
CAMLreturn(Val_unit);
}

CAMLprim value dune_reset_pthread_cwd(value unit) {
CAMLparam1(unit);
caml_invalid_argument("__pthread_fchdir not implemented");
CAMLreturn(Val_unit);
}

#endif

#if __linux__
Expand Down
29 changes: 29 additions & 0 deletions test/expect-tests/csexp_rpc/csexp_rpc_tests.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,35 @@ let temp_rpc_dir () =
Temp.temp_dir ~parent_dir:(Path.of_string ".") ~prefix:"test" ~suffix:"dune_rpc"
;;

let%expect_test "long unix socket bind restores thread cwd inheritance" =
let cwd_inherits_process_cwd =
if Platform.OS.value <> Darwin
then true
else (
let old_cwd = Sys.getcwd () in
let server =
let socket =
let tmp_dir = temp_rpc_dir () in
let socket_dir = Path.relative tmp_dir (String.make 104 'a') in
Path.relative socket_dir "dunerpc.sock" |> Path.to_absolute_filename
in
server (Unix.ADDR_UNIX socket)
in
let new_cwd = temp_rpc_dir () |> Path.to_absolute_filename in
let chdir_from_another_thread dir =
let thread = Thread.create Sys.chdir dir in
Thread.join thread
in
chdir_from_another_thread new_cwd;
let inherited = String.equal (Sys.getcwd ()) new_cwd in
chdir_from_another_thread old_cwd;
stop_server server;
inherited)
in
printfn "%b" cwd_inherits_process_cwd;
[%expect {| true |}]
;;

let%expect_test "csexp server create on unix sockets" =
(let tmp_dir = temp_rpc_dir () in
let addr : Unix.sockaddr =
Expand Down
Loading