aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert2013-07-07 11:00:14 -0700
committerPaul Eggert2013-07-07 11:00:14 -0700
commit067428c1717acd28f205c2cff93f0583eb347f4c (patch)
tree5937b119187f9900840e2c1174b408e86bb8d12b /src/process.c
parent9aff9b3864085addb02b699f9648e547a8c00e54 (diff)
downloademacs-067428c1717acd28f205c2cff93f0583eb347f4c.tar.gz
emacs-067428c1717acd28f205c2cff93f0583eb347f4c.zip
Make file descriptors close-on-exec when possible.
This simplifies Emacs a bit, since it no longer needs to worry about closing file descriptors by hand in some cases. It also fixes some unlikely races. Not all such races, as libraries often open files internally without setting close-on-exec, but it's an improvement. * admin/merge-gnulib (GNULIB_MODULES): Add fcntl, pipe2. (GNULIB_TOOL_FLAGS): Avoid binary-io, close. Do not avoid fcntl. * configure.ac (mkostemp): New function to check for. (PTY_OPEN): Pass O_CLOEXEC to posix_openpt. * lib/fcntl.c, lib/getdtablesize.c, lib/pipe2.c, m4/fcntl.m4: * m4/getdtablesize.m4, m4/pipe2.m4: New files, taken from gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * nt/gnulib.mk: Remove empty gl_GNULIB_ENABLED_verify section; otherwise, gnulib-tool complains given close-on-exec changes. * nt/inc/ms-w32.h (pipe): Remove. * nt/mingw-cfg.site (ac_cv_func_fcntl, gl_cv_func_fcntl_f_dupfd_cloexec) (gl_cv_func_fcntl_f_dupfd_works, ac_cv_func_pipe2): New vars. * src/alloc.c (valid_pointer_p) [!WINDOWSNT]: * src/callproc.c (Fcall_process) [!MSDOS]: * src/emacs.c (main) [!DOS_NT]: * src/nsterm.m (ns_term_init): * src/process.c (create_process): Use 'pipe2' with O_CLOEXEC instead of 'pipe'. * src/emacs.c (Fcall_process_region) [HAVE_MKOSTEMP]: * src/filelock.c (create_lock_file) [HAVE_MKOSTEMP]: Prefer mkostemp with O_CLOEXEC to mkstemp. * src/callproc.c (relocate_fd) [!WINDOWSNT]: * src/emacs.c (main): Use F_DUPFD_CLOEXEC, not plain F_DUPFD. No need to use fcntl (..., F_SETFD, FD_CLOEXEC), since we're now using pipe2. * src/filelock.c (create_lock_file) [! HAVE_MKOSTEMP]: Make the resulting file descriptor close-on-exec. * src/lisp.h, src/lread.c, src/process.c (close_load_descs, close_process_descs): * src/lread.c (load_descriptor_list, load_descriptor_unwind): Remove; no longer needed. All uses removed. * src/process.c (SOCK_CLOEXEC): Define to 0 if not supplied by system. (close_on_exec, accept4, process_socket) [!SOCK_CLOEXEC]: New functions. (socket) [!SOCK_CLOEXEC]: Supply a substitute. (Fmake_network_process, Fnetwork_interface_list): (Fnetwork_interface_info, server_accept_connection): Make newly-created socket close-on-exec. * src/sysdep.c (emacs_open, emacs_fopen): Make new-created descriptor close-on-exec. * src/w32.c (fcntl): Support F_DUPFD_CLOEXEC well enough for Emacs. * src/w32.c, src/w32.h (pipe2): Rename from 'pipe', with new flags arg. Fixes: debbugs:14803
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c91
1 files changed, 38 insertions, 53 deletions
diff --git a/src/process.c b/src/process.c
index b77fb97168a..cad42470bc1 100644
--- a/src/process.c
+++ b/src/process.c
@@ -135,6 +135,34 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
135 EMACS_TIME *, void *); 135 EMACS_TIME *, void *);
136#endif 136#endif
137 137
138#ifndef SOCK_CLOEXEC
139# define SOCK_CLOEXEC 0
140
141/* Emulate GNU/Linux accept4 and socket well enough for this module. */
142
143static int
144close_on_exec (int fd)
145{
146 if (0 <= fd)
147 fcntl (fd, F_SETFD, FD_CLOEXEC);
148 return fd;
149}
150
151static int
152accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
153{
154 return close_on_exec (accept (sockfd, addr, addrlen));
155}
156
157static int
158process_socket (int domain, int type, int protocol)
159{
160 return close_on_exec (socket (domain, type, protocol));
161}
162# undef socket
163# define socket(domain, type, protocol) process_socket (domain, type, protocol)
164#endif
165
138/* Work around GCC 4.7.0 bug with strict overflow checking; see 166/* Work around GCC 4.7.0 bug with strict overflow checking; see
139 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. 167 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
140 These lines can be removed once the GCC bug is fixed. */ 168 These lines can be removed once the GCC bug is fixed. */
@@ -1619,14 +1647,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1619 else 1647 else
1620#endif /* HAVE_PTYS */ 1648#endif /* HAVE_PTYS */
1621 { 1649 {
1622 int tem; 1650 if (pipe2 (sv, O_CLOEXEC) != 0)
1623 tem = pipe (sv);
1624 if (tem < 0)
1625 report_file_error ("Creating pipe", Qnil); 1651 report_file_error ("Creating pipe", Qnil);
1626 inchannel = sv[0]; 1652 inchannel = sv[0];
1627 forkout = sv[1]; 1653 forkout = sv[1];
1628 tem = pipe (sv); 1654 if (pipe2 (sv, O_CLOEXEC) != 0)
1629 if (tem < 0)
1630 { 1655 {
1631 emacs_close (inchannel); 1656 emacs_close (inchannel);
1632 emacs_close (forkout); 1657 emacs_close (forkout);
@@ -1637,29 +1662,14 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1637 } 1662 }
1638 1663
1639#ifndef WINDOWSNT 1664#ifndef WINDOWSNT
1640 { 1665 if (pipe2 (wait_child_setup, O_CLOEXEC) != 0)
1641 int tem; 1666 report_file_error ("Creating pipe", Qnil);
1642
1643 tem = pipe (wait_child_setup);
1644 if (tem < 0)
1645 report_file_error ("Creating pipe", Qnil);
1646 tem = fcntl (wait_child_setup[1], F_GETFD, 0);
1647 if (tem >= 0)
1648 tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
1649 if (tem < 0)
1650 {
1651 emacs_close (wait_child_setup[0]);
1652 emacs_close (wait_child_setup[1]);
1653 report_file_error ("Setting file descriptor flags", Qnil);
1654 }
1655 }
1656#endif 1667#endif
1657 1668
1658 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1669 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1659 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1670 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1660 1671
1661 /* Record this as an active process, with its channels. 1672 /* Record this as an active process, with its channels. */
1662 As a result, child_setup will close Emacs's side of the pipes. */
1663 chan_process[inchannel] = process; 1673 chan_process[inchannel] = process;
1664 XPROCESS (process)->infd = inchannel; 1674 XPROCESS (process)->infd = inchannel;
1665 XPROCESS (process)->outfd = outchannel; 1675 XPROCESS (process)->outfd = outchannel;
@@ -3135,7 +3145,8 @@ usage: (make-network-process &rest ARGS) */)
3135 retry_connect: 3145 retry_connect:
3136#endif 3146#endif
3137 3147
3138 s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); 3148 s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC,
3149 lres->ai_protocol);
3139 if (s < 0) 3150 if (s < 0)
3140 { 3151 {
3141 xerrno = errno; 3152 xerrno = errno;
@@ -3532,7 +3543,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
3532 int s; 3543 int s;
3533 Lisp_Object res; 3544 Lisp_Object res;
3534 3545
3535 s = socket (AF_INET, SOCK_STREAM, 0); 3546 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3536 if (s < 0) 3547 if (s < 0)
3537 return Qnil; 3548 return Qnil;
3538 3549
@@ -3688,7 +3699,7 @@ FLAGS is the current flags of the interface. */)
3688 error ("interface name too long"); 3699 error ("interface name too long");
3689 strcpy (rq.ifr_name, SSDATA (ifname)); 3700 strcpy (rq.ifr_name, SSDATA (ifname));
3690 3701
3691 s = socket (AF_INET, SOCK_STREAM, 0); 3702 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3692 if (s < 0) 3703 if (s < 0)
3693 return Qnil; 3704 return Qnil;
3694 3705
@@ -3984,7 +3995,7 @@ server_accept_connection (Lisp_Object server, int channel)
3984 } saddr; 3995 } saddr;
3985 socklen_t len = sizeof saddr; 3996 socklen_t len = sizeof saddr;
3986 3997
3987 s = accept (channel, &saddr.sa, &len); 3998 s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
3988 3999
3989 if (s < 0) 4000 if (s < 0)
3990 { 4001 {
@@ -6858,32 +6869,6 @@ setup_process_coding_systems (Lisp_Object process)
6858#endif 6869#endif
6859} 6870}
6860 6871
6861/* Close all descriptors currently in use for communication
6862 with subprocess. This is used in a newly-forked subprocess
6863 to get rid of irrelevant descriptors. */
6864
6865void
6866close_process_descs (void)
6867{
6868#ifndef DOS_NT
6869 int i;
6870 for (i = 0; i < MAXDESC; i++)
6871 {
6872 Lisp_Object process;
6873 process = chan_process[i];
6874 if (!NILP (process))
6875 {
6876 int in = XPROCESS (process)->infd;
6877 int out = XPROCESS (process)->outfd;
6878 if (in >= 0)
6879 emacs_close (in);
6880 if (out >= 0 && in != out)
6881 emacs_close (out);
6882 }
6883 }
6884#endif
6885}
6886
6887DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0, 6872DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
6888 doc: /* Return the (or a) process associated with BUFFER. 6873 doc: /* Return the (or a) process associated with BUFFER.
6889BUFFER may be a buffer or the name of one. */) 6874BUFFER may be a buffer or the name of one. */)