aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/ChangeLog38
-rw-r--r--src/alloc.c2
-rw-r--r--src/callproc.c21
-rw-r--r--src/emacs.c7
-rw-r--r--src/filelock.c15
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c33
-rw-r--r--src/nsterm.m2
-rw-r--r--src/process.c91
-rw-r--r--src/sysdep.c34
-rw-r--r--src/w32.c13
-rw-r--r--src/w32.h2
12 files changed, 140 insertions, 120 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 069d39ce6be..07285d564b2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,41 @@
12013-07-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Make file descriptors close-on-exec when possible (Bug#14803).
4 This simplifies Emacs a bit, since it no longer needs to worry
5 about closing file descriptors by hand in some cases.
6 It also fixes some unlikely races. Not all such races, as
7 libraries often open files internally without setting
8 close-on-exec, but it's an improvement.
9 * alloc.c (valid_pointer_p) [!WINDOWSNT]:
10 * callproc.c (Fcall_process) [!MSDOS]:
11 * emacs.c (main) [!DOS_NT]:
12 * nsterm.m (ns_term_init):
13 * process.c (create_process):
14 Use 'pipe2' with O_CLOEXEC instead of 'pipe'.
15 * emacs.c (Fcall_process_region) [HAVE_MKOSTEMP]:
16 * filelock.c (create_lock_file) [HAVE_MKOSTEMP]:
17 Prefer mkostemp with O_CLOEXEC to mkstemp.
18 * callproc.c (relocate_fd) [!WINDOWSNT]:
19 * emacs.c (main): Use F_DUPFD_CLOEXEC, not plain F_DUPFD.
20 No need to use fcntl (..., F_SETFD, FD_CLOEXEC), since we're
21 now using pipe2.
22 * filelock.c (create_lock_file) [! HAVE_MKOSTEMP]:
23 Make the resulting file descriptor close-on-exec.
24 * lisp.h, lread.c, process.c (close_load_descs, close_process_descs):
25 * lread.c (load_descriptor_list, load_descriptor_unwind):
26 Remove; no longer needed. All uses removed.
27 * process.c (SOCK_CLOEXEC): Define to 0 if not supplied by system.
28 (close_on_exec, accept4, process_socket) [!SOCK_CLOEXEC]:
29 New functions.
30 (socket) [!SOCK_CLOEXEC]: Supply a substitute.
31 (Fmake_network_process, Fnetwork_interface_list):
32 (Fnetwork_interface_info, server_accept_connection):
33 Make newly-created socket close-on-exec.
34 * sysdep.c (emacs_open, emacs_fopen):
35 Make new-created descriptor close-on-exec.
36 * w32.c (fcntl): Support F_DUPFD_CLOEXEC well enough for Emacs.
37 * w32.c, w32.h (pipe2): Rename from 'pipe', with new flags arg.
38
12013-07-07 Jan Djärv <jan.h.d@swipnet.se> 392013-07-07 Jan Djärv <jan.h.d@swipnet.se>
2 40
3 * nsterm.m (sendEvent:): Propagate keyboard events to modal windows 41 * nsterm.m (sendEvent:): Propagate keyboard events to modal windows
diff --git a/src/alloc.c b/src/alloc.c
index a31a176caa7..b71cdb98d78 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4741,7 +4741,7 @@ valid_pointer_p (void *p)
4741 Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may 4741 Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
4742 not validate p in that case. */ 4742 not validate p in that case. */
4743 4743
4744 if (pipe (fd) == 0) 4744 if (pipe2 (fd, O_CLOEXEC) == 0)
4745 { 4745 {
4746 bool valid = emacs_write (fd[1], (char *) p, 16) == 16; 4746 bool valid = emacs_write (fd[1], (char *) p, 16) == 16;
4747 emacs_close (fd[1]); 4747 emacs_close (fd[1]);
diff --git a/src/callproc.c b/src/callproc.c
index 185dc9a493e..3e70b1c2e49 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -519,7 +519,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
519 { 519 {
520#ifndef MSDOS 520#ifndef MSDOS
521 int fd[2]; 521 int fd[2];
522 if (pipe (fd) == -1) 522 if (pipe2 (fd, O_CLOEXEC) != 0)
523 { 523 {
524 int pipe_errno = errno; 524 int pipe_errno = errno;
525 emacs_close (filefd); 525 emacs_close (filefd);
@@ -1036,12 +1036,16 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1036 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); 1036 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
1037 coding_systems = Qt; 1037 coding_systems = Qt;
1038 1038
1039#ifdef HAVE_MKSTEMP 1039#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
1040 { 1040 {
1041 int fd; 1041 int fd;
1042 1042
1043 block_input (); 1043 block_input ();
1044# ifdef HAVE_MKOSTEMP
1045 fd = mkostemp (tempfile, O_CLOEXEC);
1046# else
1044 fd = mkstemp (tempfile); 1047 fd = mkstemp (tempfile);
1048# endif
1045 unblock_input (); 1049 unblock_input ();
1046 if (fd == -1) 1050 if (fd == -1)
1047 report_file_error ("Failed to open temporary file", 1051 report_file_error ("Failed to open temporary file",
@@ -1184,15 +1188,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1184 1188
1185 pid_t pid = getpid (); 1189 pid_t pid = getpid ();
1186 1190
1187 /* Close Emacs's descriptors that this process should not have. */
1188 close_process_descs ();
1189
1190 /* DOS_NT isn't in a vfork, so if we are in the middle of load-file,
1191 we will lose if we call close_load_descs here. */
1192#ifndef DOS_NT
1193 close_load_descs ();
1194#endif
1195
1196 /* Note that use of alloca is always safe here. It's obvious for systems 1191 /* Note that use of alloca is always safe here. It's obvious for systems
1197 that do not have true vfork or that have true (stack) alloca. 1192 that do not have true vfork or that have true (stack) alloca.
1198 If using vfork and C_ALLOCA (when Emacs used to include 1193 If using vfork and C_ALLOCA (when Emacs used to include
@@ -1354,9 +1349,11 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1354 emacs_close (1); 1349 emacs_close (1);
1355 emacs_close (2); 1350 emacs_close (2);
1356 1351
1352 /* Redirect file descriptors and clear FD_CLOEXEC on the redirected ones. */
1357 dup2 (in, 0); 1353 dup2 (in, 0);
1358 dup2 (out, 1); 1354 dup2 (out, 1);
1359 dup2 (err, 2); 1355 dup2 (err, 2);
1356
1360 emacs_close (in); 1357 emacs_close (in);
1361 if (out != in) 1358 if (out != in)
1362 emacs_close (out); 1359 emacs_close (out);
@@ -1394,7 +1391,7 @@ relocate_fd (int fd, int minfd)
1394 return fd; 1391 return fd;
1395 else 1392 else
1396 { 1393 {
1397 int new = fcntl (fd, F_DUPFD, minfd); 1394 int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd);
1398 if (new == -1) 1395 if (new == -1)
1399 { 1396 {
1400 const char *message_1 = "Error while setting up child: "; 1397 const char *message_1 = "Error while setting up child: ";
diff --git a/src/emacs.c b/src/emacs.c
index 6ba01d1a443..e4412e2ea1a 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -889,7 +889,7 @@ main (int argc, char **argv)
889 emacs_close (0); 889 emacs_close (0);
890 emacs_close (1); 890 emacs_close (1);
891 result = emacs_open (term, O_RDWR, 0); 891 result = emacs_open (term, O_RDWR, 0);
892 if (result < 0 || dup (0) < 0) 892 if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0)
893 { 893 {
894 char *errstring = strerror (errno); 894 char *errstring = strerror (errno);
895 fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring); 895 fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring);
@@ -969,7 +969,7 @@ main (int argc, char **argv)
969 use a pipe for synchronization. The parent waits for the child 969 use a pipe for synchronization. The parent waits for the child
970 to close its end of the pipe (using `daemon-initialized') 970 to close its end of the pipe (using `daemon-initialized')
971 before exiting. */ 971 before exiting. */
972 if (pipe (daemon_pipe) == -1) 972 if (pipe2 (daemon_pipe, O_CLOEXEC) != 0)
973 { 973 {
974 fprintf (stderr, "Cannot pipe!\n"); 974 fprintf (stderr, "Cannot pipe!\n");
975 exit (1); 975 exit (1);
@@ -1065,9 +1065,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1065 daemon_name = xstrdup (dname_arg); 1065 daemon_name = xstrdup (dname_arg);
1066 /* Close unused reading end of the pipe. */ 1066 /* Close unused reading end of the pipe. */
1067 close (daemon_pipe[0]); 1067 close (daemon_pipe[0]);
1068 /* Make sure that the used end of the pipe is closed on exec, so
1069 that it is not accessible to programs started from .emacs. */
1070 fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
1071 1068
1072 setsid (); 1069 setsid ();
1073#else /* DOS_NT */ 1070#else /* DOS_NT */
diff --git a/src/filelock.c b/src/filelock.c
index de6aba8385c..1fcd2432484 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -416,8 +416,13 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
416 memcpy (nonce, lfname, lfdirlen); 416 memcpy (nonce, lfname, lfdirlen);
417 strcpy (nonce + lfdirlen, nonce_base); 417 strcpy (nonce + lfdirlen, nonce_base);
418 418
419#if HAVE_MKSTEMP 419#if HAVE_MKOSTEMP
420 /* Prefer mkstemp if available, as it avoids a race between 420 /* Prefer mkostemp to mkstemp, as it avoids a window where FD is
421 temporarily open without close-on-exec. */
422 fd = mkostemp (nonce, O_BINARY | O_CLOEXEC);
423 need_fchmod = 1;
424#elif HAVE_MKSTEMP
425 /* Prefer mkstemp to mktemp, as it avoids a race between
421 mktemp and emacs_open. */ 426 mktemp and emacs_open. */
422 fd = mkstemp (nonce); 427 fd = mkstemp (nonce);
423 need_fchmod = 1; 428 need_fchmod = 1;
@@ -432,7 +437,11 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
432 err = errno; 437 err = errno;
433 else 438 else
434 { 439 {
435 ptrdiff_t lock_info_len = strlen (lock_info_str); 440 ptrdiff_t lock_info_len;
441#if ! HAVE_MKOSTEMP
442 fcntl (fd, F_SETFD, FD_CLOEXEC);
443#endif
444 lock_info_len = strlen (lock_info_str);
436 err = 0; 445 err = 0;
437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len 446 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
438 || (need_fchmod && fchmod (fd, world_readable) != 0)) 447 || (need_fchmod && fchmod (fd, world_readable) != 0))
diff --git a/src/lisp.h b/src/lisp.h
index 5d6fa760108..692f73cdbc3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3668,7 +3668,6 @@ extern Lisp_Object string_to_number (char const *, int, bool);
3668extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), 3668extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
3669 Lisp_Object); 3669 Lisp_Object);
3670extern void dir_warning (const char *, Lisp_Object); 3670extern void dir_warning (const char *, Lisp_Object);
3671extern void close_load_descs (void);
3672extern void init_obarray (void); 3671extern void init_obarray (void);
3673extern void init_lread (void); 3672extern void init_lread (void);
3674extern void syms_of_lread (void); 3673extern void syms_of_lread (void);
@@ -3995,7 +3994,6 @@ extern void delete_keyboard_wait_descriptor (int);
3995extern void add_gpm_wait_descriptor (int); 3994extern void add_gpm_wait_descriptor (int);
3996extern void delete_gpm_wait_descriptor (int); 3995extern void delete_gpm_wait_descriptor (int);
3997#endif 3996#endif
3998extern void close_process_descs (void);
3999extern void init_process_emacs (void); 3997extern void init_process_emacs (void);
4000extern void syms_of_process (void); 3998extern void syms_of_process (void);
4001extern void setup_process_coding_systems (Lisp_Object); 3999extern void setup_process_coding_systems (Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index 2ceeb106653..83d2e8d954a 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -95,9 +95,6 @@ static Lisp_Object Qload_in_progress;
95 It must be set to nil before all top-level calls to read0. */ 95 It must be set to nil before all top-level calls to read0. */
96static Lisp_Object read_objects; 96static Lisp_Object read_objects;
97 97
98/* List of descriptors now open for Fload. */
99static Lisp_Object load_descriptor_list;
100
101/* File for get_file_char to read from. Use by load. */ 98/* File for get_file_char to read from. Use by load. */
102static FILE *instream; 99static FILE *instream;
103 100
@@ -149,7 +146,6 @@ static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
149 Lisp_Object, Lisp_Object, 146 Lisp_Object, Lisp_Object,
150 Lisp_Object, Lisp_Object); 147 Lisp_Object, Lisp_Object);
151static Lisp_Object load_unwind (Lisp_Object); 148static Lisp_Object load_unwind (Lisp_Object);
152static Lisp_Object load_descriptor_unwind (Lisp_Object);
153 149
154/* Functions that read one byte from the current source READCHARFUN 150/* Functions that read one byte from the current source READCHARFUN
155 or unreads one byte. If the integer argument C is -1, it returns 151 or unreads one byte. If the integer argument C is -1, it returns
@@ -1328,11 +1324,8 @@ Return t if the file exists and loads successfully. */)
1328 } 1324 }
1329 1325
1330 record_unwind_protect (load_unwind, make_save_pointer (stream)); 1326 record_unwind_protect (load_unwind, make_save_pointer (stream));
1331 record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
1332 specbind (Qload_file_name, found); 1327 specbind (Qload_file_name, found);
1333 specbind (Qinhibit_file_name_operation, Qnil); 1328 specbind (Qinhibit_file_name_operation, Qnil);
1334 load_descriptor_list
1335 = Fcons (make_number (fileno (stream)), load_descriptor_list);
1336 specbind (Qload_in_progress, Qt); 1329 specbind (Qload_in_progress, Qt);
1337 1330
1338 instream = stream; 1331 instream = stream;
@@ -1395,26 +1388,6 @@ load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */
1395 } 1388 }
1396 return Qnil; 1389 return Qnil;
1397} 1390}
1398
1399static Lisp_Object
1400load_descriptor_unwind (Lisp_Object oldlist)
1401{
1402 load_descriptor_list = oldlist;
1403 return Qnil;
1404}
1405
1406/* Close all descriptors in use for Floads.
1407 This is used when starting a subprocess. */
1408
1409void
1410close_load_descs (void)
1411{
1412#ifndef WINDOWSNT
1413 Lisp_Object tail;
1414 for (tail = load_descriptor_list; CONSP (tail); tail = XCDR (tail))
1415 emacs_close (XFASTINT (XCAR (tail)));
1416#endif
1417}
1418 1391
1419static bool 1392static bool
1420complete_filename_p (Lisp_Object pathname) 1393complete_filename_p (Lisp_Object pathname)
@@ -4376,9 +4349,6 @@ init_lread (void)
4376 4349
4377 load_in_progress = 0; 4350 load_in_progress = 0;
4378 Vload_file_name = Qnil; 4351 Vload_file_name = Qnil;
4379
4380 load_descriptor_list = Qnil;
4381
4382 Vstandard_input = Qt; 4352 Vstandard_input = Qt;
4383 Vloads_in_progress = Qnil; 4353 Vloads_in_progress = Qnil;
4384} 4354}
@@ -4651,9 +4621,6 @@ variables, this must be set in the first line of a file. */);
4651 4621
4652 /* Vsource_directory was initialized in init_lread. */ 4622 /* Vsource_directory was initialized in init_lread. */
4653 4623
4654 load_descriptor_list = Qnil;
4655 staticpro (&load_descriptor_list);
4656
4657 DEFSYM (Qcurrent_load_list, "current-load-list"); 4624 DEFSYM (Qcurrent_load_list, "current-load-list");
4658 DEFSYM (Qstandard_input, "standard-input"); 4625 DEFSYM (Qstandard_input, "standard-input");
4659 DEFSYM (Qread_char, "read-char"); 4626 DEFSYM (Qread_char, "read-char");
diff --git a/src/nsterm.m b/src/nsterm.m
index dfb82edd738..074a5adf78c 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -4142,7 +4142,7 @@ ns_term_init (Lisp_Object display_name)
4142 4142
4143 if (selfds[0] == -1) 4143 if (selfds[0] == -1)
4144 { 4144 {
4145 if (pipe (selfds) == -1) 4145 if (pipe2 (selfds, O_CLOEXEC) != 0)
4146 { 4146 {
4147 fprintf (stderr, "Failed to create pipe: %s\n", 4147 fprintf (stderr, "Failed to create pipe: %s\n",
4148 emacs_strerror (errno)); 4148 emacs_strerror (errno));
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. */)
diff --git a/src/sysdep.c b/src/sysdep.c
index 91e941a2050..faca7fae461 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -543,8 +543,6 @@ sys_subshell (void)
543#endif 543#endif
544 } 544 }
545 545
546 close_process_descs (); /* Close Emacs's pipes/ptys */
547
548#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 546#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
549 { 547 {
550 char *epwd = getenv ("PWD"); 548 char *epwd = getenv ("PWD");
@@ -2152,6 +2150,8 @@ emacs_abort (void)
2152#endif 2150#endif
2153 2151
2154/* Open FILE for Emacs use, using open flags OFLAG and mode MODE. 2152/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
2153 Arrange for subprograms to not inherit the file descriptor.
2154 Prefer a method that is multithread-safe, if available.
2155 Do not fail merely because the open was interrupted by a signal. 2155 Do not fail merely because the open was interrupted by a signal.
2156 Allow the user to quit. */ 2156 Allow the user to quit. */
2157 2157
@@ -2159,8 +2159,11 @@ int
2159emacs_open (const char *file, int oflags, int mode) 2159emacs_open (const char *file, int oflags, int mode)
2160{ 2160{
2161 int fd; 2161 int fd;
2162 oflags |= O_CLOEXEC;
2162 while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) 2163 while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
2163 QUIT; 2164 QUIT;
2165 if (! O_CLOEXEC && 0 <= fd)
2166 fcntl (fd, F_SETFD, FD_CLOEXEC);
2164 return fd; 2167 return fd;
2165} 2168}
2166 2169
@@ -2170,10 +2173,29 @@ emacs_open (const char *file, int oflags, int mode)
2170FILE * 2173FILE *
2171emacs_fopen (char const *file, char const *mode) 2174emacs_fopen (char const *file, char const *mode)
2172{ 2175{
2173 FILE *fp; 2176 int fd, omode, oflags;
2174 while (! (fp = fopen (file, mode)) && errno == EINTR) 2177 int bflag = 0;
2175 QUIT; 2178 char const *m = mode;
2176 return fp; 2179
2180 switch (*m++)
2181 {
2182 case 'r': omode = O_RDONLY; oflags = 0; break;
2183 case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break;
2184 case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break;
2185 default: emacs_abort ();
2186 }
2187
2188 while (*m)
2189 switch (*m++)
2190 {
2191 case '+': omode = O_RDWR; break;
2192 case 'b': bflag = O_BINARY; break;
2193 case 't': bflag = O_TEXT; break;
2194 default: /* Ignore. */ break;
2195 }
2196
2197 fd = emacs_open (file, omode | oflags | bflag, 0666);
2198 return fd < 0 ? 0 : fdopen (fd, mode);
2177} 2199}
2178 2200
2179int 2201int
diff --git a/src/w32.c b/src/w32.c
index 230479cd61a..46aebe8b634 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -6719,10 +6719,16 @@ sys_sendto (int s, const char * buf, int len, int flags,
6719} 6719}
6720 6720
6721/* Windows does not have an fcntl function. Provide an implementation 6721/* Windows does not have an fcntl function. Provide an implementation
6722 solely for making sockets non-blocking. */ 6722 good enough for Emacs. */
6723int 6723int
6724fcntl (int s, int cmd, int options) 6724fcntl (int s, int cmd, int options)
6725{ 6725{
6726 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
6727 invoked in a context where fd1 is closed and all descriptors less
6728 than fd1 are open, so sys_dup is an adequate implementation. */
6729 if (cmd == F_DUPFD_CLOEXEC)
6730 return sys_dup (s);
6731
6726 if (winsock_lib == NULL) 6732 if (winsock_lib == NULL)
6727 { 6733 {
6728 errno = ENETDOWN; 6734 errno = ENETDOWN;
@@ -6864,13 +6870,14 @@ sys_dup2 (int src, int dst)
6864 return rc; 6870 return rc;
6865} 6871}
6866 6872
6867/* Unix pipe() has only one arg */
6868int 6873int
6869sys_pipe (int * phandles) 6874pipe2 (int * phandles, int pipe2_flags)
6870{ 6875{
6871 int rc; 6876 int rc;
6872 unsigned flags; 6877 unsigned flags;
6873 6878
6879 eassert (pipe2_flags == O_CLOEXEC);
6880
6874 /* make pipe handles non-inheritable; when we spawn a child, we 6881 /* make pipe handles non-inheritable; when we spawn a child, we
6875 replace the relevant handle with an inheritable one. Also put 6882 replace the relevant handle with an inheritable one. Also put
6876 pipes into binary mode; we will do text mode translation ourselves 6883 pipes into binary mode; we will do text mode translation ourselves
diff --git a/src/w32.h b/src/w32.h
index 17da0778db1..9c1f1efa699 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -188,7 +188,7 @@ extern int random (void);
188 188
189extern int fchmod (int, mode_t); 189extern int fchmod (int, mode_t);
190extern int sys_rename_replace (char const *, char const *, BOOL); 190extern int sys_rename_replace (char const *, char const *, BOOL);
191extern int sys_pipe (int *); 191extern int pipe2 (int *, int);
192 192
193extern void set_process_dir (char *); 193extern void set_process_dir (char *);
194extern int sys_spawnve (int, char *, char **, char **); 194extern int sys_spawnve (int, char *, char **, char **);