Skip to content
Open
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
30 changes: 29 additions & 1 deletion sshfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4518,7 +4518,11 @@ int main(int argc, char *argv[])
exit(1);
}

#if !defined(__CYGWIN__)
/*
* On macOS the FD_CLOEXEC fcntl is deferred until after
* fuse_daemonize() below; see the comment there.
*/
#if !defined(__CYGWIN__) && !defined(__APPLE__)
res = fcntl(fuse_session_fd(se), F_SETFD, FD_CLOEXEC);
if (res == -1)
perror("WARNING: failed to set FD_CLOEXEC on fuse device");
Expand All @@ -4542,6 +4546,30 @@ int main(int argc, char *argv[])
exit(1);
}

#ifdef __APPLE__
/*
* macFUSE 5.3.3+ mounts lazily: fuse_mount() only records the request,
* and the real mount (and its XPC channel) is created on first use.
* On macOS fuse_session_fd() is such a first use -- it triggers the
* delayed mount and marks the mount as started, after which
* fuse_daemonize() refuses to fork and stays in the foreground
* ("daemonize requested after mount started; continuing in foreground").
*
* So defer the FD_CLOEXEC fcntl until here, after daemonizing: the
* mount is then created in the daemon child, where its XPC connection
* survives, and daemonization still forks as before. The fuse fd does
* not exist yet while the first ssh child is spawned in ssh_connect()
* above, so nothing can leak in that window; setting FD_CLOEXEC now
* still protects the ssh children spawned later on reconnect.
*
* See macFUSE commit 867b5cdb ("Defer mount process until first use on
* macOS") and https://github.com/libfuse/sshfs/issues/338
*/
res = fcntl(fuse_session_fd(se), F_SETFD, FD_CLOEXEC);
if (res == -1)
perror("WARNING: failed to set FD_CLOEXEC on fuse device");
#endif

if (sshfs.singlethread)
res = fuse_loop(fuse);
else
Expand Down