diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 38 | ||||
| -rw-r--r-- | src/alloc.c | 2 | ||||
| -rw-r--r-- | src/callproc.c | 21 | ||||
| -rw-r--r-- | src/emacs.c | 7 | ||||
| -rw-r--r-- | src/filelock.c | 15 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/lread.c | 33 | ||||
| -rw-r--r-- | src/nsterm.m | 2 | ||||
| -rw-r--r-- | src/process.c | 91 | ||||
| -rw-r--r-- | src/sysdep.c | 34 | ||||
| -rw-r--r-- | src/w32.c | 13 | ||||
| -rw-r--r-- | src/w32.h | 2 |
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 @@ | |||
| 1 | 2013-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 | |||
| 1 | 2013-07-07 Jan Djärv <jan.h.d@swipnet.se> | 39 | 2013-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); | |||
| 3668 | extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), | 3668 | extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), |
| 3669 | Lisp_Object); | 3669 | Lisp_Object); |
| 3670 | extern void dir_warning (const char *, Lisp_Object); | 3670 | extern void dir_warning (const char *, Lisp_Object); |
| 3671 | extern void close_load_descs (void); | ||
| 3672 | extern void init_obarray (void); | 3671 | extern void init_obarray (void); |
| 3673 | extern void init_lread (void); | 3672 | extern void init_lread (void); |
| 3674 | extern void syms_of_lread (void); | 3673 | extern void syms_of_lread (void); |
| @@ -3995,7 +3994,6 @@ extern void delete_keyboard_wait_descriptor (int); | |||
| 3995 | extern void add_gpm_wait_descriptor (int); | 3994 | extern void add_gpm_wait_descriptor (int); |
| 3996 | extern void delete_gpm_wait_descriptor (int); | 3995 | extern void delete_gpm_wait_descriptor (int); |
| 3997 | #endif | 3996 | #endif |
| 3998 | extern void close_process_descs (void); | ||
| 3999 | extern void init_process_emacs (void); | 3997 | extern void init_process_emacs (void); |
| 4000 | extern void syms_of_process (void); | 3998 | extern void syms_of_process (void); |
| 4001 | extern void setup_process_coding_systems (Lisp_Object); | 3999 | extern 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. */ |
| 96 | static Lisp_Object read_objects; | 96 | static Lisp_Object read_objects; |
| 97 | 97 | ||
| 98 | /* List of descriptors now open for Fload. */ | ||
| 99 | static 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. */ |
| 102 | static FILE *instream; | 99 | static 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); |
| 151 | static Lisp_Object load_unwind (Lisp_Object); | 148 | static Lisp_Object load_unwind (Lisp_Object); |
| 152 | static 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 | |||
| 1399 | static Lisp_Object | ||
| 1400 | load_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 | |||
| 1409 | void | ||
| 1410 | close_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 | ||
| 1419 | static bool | 1392 | static bool |
| 1420 | complete_filename_p (Lisp_Object pathname) | 1393 | complete_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 | |||
| 143 | static int | ||
| 144 | close_on_exec (int fd) | ||
| 145 | { | ||
| 146 | if (0 <= fd) | ||
| 147 | fcntl (fd, F_SETFD, FD_CLOEXEC); | ||
| 148 | return fd; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int | ||
| 152 | accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) | ||
| 153 | { | ||
| 154 | return close_on_exec (accept (sockfd, addr, addrlen)); | ||
| 155 | } | ||
| 156 | |||
| 157 | static int | ||
| 158 | process_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 | |||
| 6865 | void | ||
| 6866 | close_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 | |||
| 6887 | DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0, | 6872 | DEFUN ("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. |
| 6889 | BUFFER may be a buffer or the name of one. */) | 6874 | BUFFER 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 | |||
| 2159 | emacs_open (const char *file, int oflags, int mode) | 2159 | emacs_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) | |||
| 2170 | FILE * | 2173 | FILE * |
| 2171 | emacs_fopen (char const *file, char const *mode) | 2174 | emacs_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 | ||
| 2179 | int | 2201 | int |
| @@ -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. */ |
| 6723 | int | 6723 | int |
| 6724 | fcntl (int s, int cmd, int options) | 6724 | fcntl (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 */ | ||
| 6868 | int | 6873 | int |
| 6869 | sys_pipe (int * phandles) | 6874 | pipe2 (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 |
| @@ -188,7 +188,7 @@ extern int random (void); | |||
| 188 | 188 | ||
| 189 | extern int fchmod (int, mode_t); | 189 | extern int fchmod (int, mode_t); |
| 190 | extern int sys_rename_replace (char const *, char const *, BOOL); | 190 | extern int sys_rename_replace (char const *, char const *, BOOL); |
| 191 | extern int sys_pipe (int *); | 191 | extern int pipe2 (int *, int); |
| 192 | 192 | ||
| 193 | extern void set_process_dir (char *); | 193 | extern void set_process_dir (char *); |
| 194 | extern int sys_spawnve (int, char *, char **, char **); | 194 | extern int sys_spawnve (int, char *, char **, char **); |