job-control: set CLOEXEC on pty processes. #5986

Before this change, new processes started with libuv prevented SIGHUP
from reaching pty processes (by keeping the ptmx file descriptor open).
This commit is contained in:
Matthew Malcomson
2017-01-21 14:11:30 +00:00
committed by Justin M. Keyes
parent ad1884be0d
commit f6946c68ae
7 changed files with 77 additions and 35 deletions

View File

@@ -2692,14 +2692,7 @@ static FILE *fopen_noinh_readbin(char *filename)
return NULL;
}
#ifdef HAVE_FD_CLOEXEC
{
int fdflags = fcntl(fd_tmp, F_GETFD);
if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
(void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
}
}
#endif
(void)os_set_cloexec(fd_tmp);
return fdopen(fd_tmp, READBIN);
}

View File

@@ -1742,16 +1742,11 @@ failed:
}
# endif
if (!read_buffer && !read_stdin)
close(fd); /* errors are ignored */
#ifdef HAVE_FD_CLOEXEC
else {
int fdflags = fcntl(fd, F_GETFD);
if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
(void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
}
if (!read_buffer && !read_stdin) {
close(fd); // errors are ignored
} else {
(void)os_set_cloexec(fd);
}
#endif
xfree(buffer);
if (read_stdin) {

View File

@@ -909,12 +909,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
return false;
}
#ifdef HAVE_FD_CLOEXEC
int fdflags = fcntl(mfp->mf_fd, F_GETFD);
if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
(void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
}
#endif
(void)os_set_cloexec(mfp->mf_fd);
#ifdef HAVE_SELINUX
mch_copy_sec(fname, mfp->mf_fname);
#endif

View File

@@ -439,14 +439,7 @@ void ml_setname(buf_T *buf)
EMSG(_("E301: Oops, lost the swap file!!!"));
return;
}
#ifdef HAVE_FD_CLOEXEC
{
int fdflags = fcntl(mfp->mf_fd, F_GETFD);
if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
(void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
}
}
#endif
(void)os_set_cloexec(mfp->mf_fd);
}
if (!success)
EMSG(_("E302: Could not rename swap file"));

View File

@@ -391,6 +391,35 @@ int os_open(const char* path, int flags, int mode)
return r;
}
/// Sets file descriptor `fd` to close-on-exec.
//
// @return -1 if failed to set, 0 otherwise.
int os_set_cloexec(const int fd)
{
#ifdef HAVE_FD_CLOEXEC
int e;
int fdflags = fcntl(fd, F_GETFD);
if (fdflags < 0) {
e = errno;
ELOG("Failed to get flags on descriptor %d: %s", fd, strerror(e));
errno = e;
return -1;
}
if ((fdflags & FD_CLOEXEC) == 0
&& fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC) < 0) {
e = errno;
ELOG("Failed to set CLOEXEC on descriptor %d: %s", fd, strerror(e));
errno = e;
return -1;
}
return 0;
#endif
// No FD_CLOEXEC flag. On Windows, the file should have been opened with
// O_NOINHERIT anyway.
return -1;
}
/// Close a file
///
/// @return 0 or libuv error code on failure.

View File

@@ -73,6 +73,13 @@ int pty_process_spawn(PtyProcess *ptyproc)
goto error;
}
// Other jobs and providers should not get a copy of this file descriptor.
if (os_set_cloexec(master) == -1) {
status = -errno;
ELOG("Failed to set CLOEXEC on ptmx file descriptor");
goto error;
}
if (proc->in
&& (status = set_duplicating_descriptor(master, &proc->in->uv.pipe))) {
goto error;
@@ -215,14 +222,24 @@ static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe)
ELOG("Failed to dup descriptor %d: %s", fd, strerror(errno));
return status;
}
if (os_set_cloexec(fd_dup) == -1) {
status = -errno;
ELOG("Failed to set CLOEXEC on duplicate fd");
goto error;
}
status = uv_pipe_open(pipe, fd_dup);
if (status) {
ELOG("Failed to set pipe to descriptor %d: %s",
fd_dup, uv_strerror(status));
close(fd_dup);
return status;
goto error;
}
return status;
error:
close(fd_dup);
return status;
}
static void chld_handler(uv_signal_t *handle, int signum)