diff options
| author | Philipp Stephani | 2020-12-30 23:43:07 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2020-12-31 00:18:02 +0100 |
| commit | 8bc85d46cc9214a531f2d2ecb3f5fb48af8105a6 (patch) | |
| tree | 346a7c64ac0b6a78eacdeb69b73a446d33d87266 /src/process.c | |
| parent | f43f1e32e92ef341077b4ffdfdd743b1a6d9d284 (diff) | |
| download | emacs-8bc85d46cc9214a531f2d2ecb3f5fb48af8105a6.tar.gz emacs-8bc85d46cc9214a531f2d2ecb3f5fb48af8105a6.zip | |
Manually limit file descriptors that we select on to FD_SETSIZE.
This works even if another thread or process resets the resource limit
for open file descriptors, e.g., using 'prlimit' on GNU/Linux.
* src/process.c (create_process, create_pty, Fmake_pipe_process)
(Fmake_serial_process, connect_network_socket)
(server_accept_connection): Limit file descriptors to FD_SETSIZE.
* test/src/process-tests.el (process-tests--with-raised-rlimit): New
helper macro.
(process-tests--fd-setsize-test): Rename from
'process-tests--with-many-pipes'. Increase resource limit during test
if possible.
(process-tests/fd-setsize-no-crash/make-process)
(process-tests/fd-setsize-no-crash/make-pipe-process)
(process-tests/fd-setsize-no-crash/make-network-process)
(process-tests--new-pty): Rename callers.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/process.c b/src/process.c index 7c56366d8e1..ba2bb3c9e46 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -2114,6 +2114,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 2114 | } | 2114 | } |
| 2115 | } | 2115 | } |
| 2116 | 2116 | ||
| 2117 | if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel) | ||
| 2118 | report_file_errno ("Creating pipe", Qnil, EMFILE); | ||
| 2119 | |||
| 2117 | #ifndef WINDOWSNT | 2120 | #ifndef WINDOWSNT |
| 2118 | if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) | 2121 | if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) |
| 2119 | report_file_error ("Creating pipe", Qnil); | 2122 | report_file_error ("Creating pipe", Qnil); |
| @@ -2210,6 +2213,8 @@ create_pty (Lisp_Object process) | |||
| 2210 | if (pty_fd >= 0) | 2213 | if (pty_fd >= 0) |
| 2211 | { | 2214 | { |
| 2212 | p->open_fd[SUBPROCESS_STDIN] = pty_fd; | 2215 | p->open_fd[SUBPROCESS_STDIN] = pty_fd; |
| 2216 | if (FD_SETSIZE <= pty_fd) | ||
| 2217 | report_file_errno ("Opening pty", Qnil, EMFILE); | ||
| 2213 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) | 2218 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) |
| 2214 | /* On most USG systems it does not work to open the pty's tty here, | 2219 | /* On most USG systems it does not work to open the pty's tty here, |
| 2215 | then close it and reopen it in the child. */ | 2220 | then close it and reopen it in the child. */ |
| @@ -2317,6 +2322,9 @@ usage: (make-pipe-process &rest ARGS) */) | |||
| 2317 | outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; | 2322 | outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; |
| 2318 | inchannel = p->open_fd[READ_FROM_SUBPROCESS]; | 2323 | inchannel = p->open_fd[READ_FROM_SUBPROCESS]; |
| 2319 | 2324 | ||
| 2325 | if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel) | ||
| 2326 | report_file_errno ("Creating pipe", Qnil, EMFILE); | ||
| 2327 | |||
| 2320 | fcntl (inchannel, F_SETFL, O_NONBLOCK); | 2328 | fcntl (inchannel, F_SETFL, O_NONBLOCK); |
| 2321 | fcntl (outchannel, F_SETFL, O_NONBLOCK); | 2329 | fcntl (outchannel, F_SETFL, O_NONBLOCK); |
| 2322 | 2330 | ||
| @@ -3059,6 +3067,8 @@ usage: (make-serial-process &rest ARGS) */) | |||
| 3059 | 3067 | ||
| 3060 | fd = serial_open (port); | 3068 | fd = serial_open (port); |
| 3061 | p->open_fd[SUBPROCESS_STDIN] = fd; | 3069 | p->open_fd[SUBPROCESS_STDIN] = fd; |
| 3070 | if (FD_SETSIZE <= fd) | ||
| 3071 | report_file_errno ("Opening serial port", Qnil, EMFILE); | ||
| 3062 | p->infd = fd; | 3072 | p->infd = fd; |
| 3063 | p->outfd = fd; | 3073 | p->outfd = fd; |
| 3064 | if (fd > max_desc) | 3074 | if (fd > max_desc) |
| @@ -3280,6 +3290,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3280 | if (!NILP (use_external_socket_p)) | 3290 | if (!NILP (use_external_socket_p)) |
| 3281 | { | 3291 | { |
| 3282 | socket_to_use = external_sock_fd; | 3292 | socket_to_use = external_sock_fd; |
| 3293 | eassert (socket_to_use < FD_SETSIZE); | ||
| 3283 | 3294 | ||
| 3284 | /* Ensure we don't consume the external socket twice. */ | 3295 | /* Ensure we don't consume the external socket twice. */ |
| 3285 | external_sock_fd = -1; | 3296 | external_sock_fd = -1; |
| @@ -3321,6 +3332,13 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3321 | xerrno = errno; | 3332 | xerrno = errno; |
| 3322 | continue; | 3333 | continue; |
| 3323 | } | 3334 | } |
| 3335 | if (FD_SETSIZE <= s) | ||
| 3336 | { | ||
| 3337 | emacs_close (s); | ||
| 3338 | s = -1; | ||
| 3339 | xerrno = EMFILE; | ||
| 3340 | continue; | ||
| 3341 | } | ||
| 3324 | } | 3342 | } |
| 3325 | 3343 | ||
| 3326 | if (p->is_non_blocking_client && ! (SOCK_NONBLOCK && socket_to_use < 0)) | 3344 | if (p->is_non_blocking_client && ! (SOCK_NONBLOCK && socket_to_use < 0)) |
| @@ -4782,6 +4800,13 @@ server_accept_connection (Lisp_Object server, int channel) | |||
| 4782 | 4800 | ||
| 4783 | s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC); | 4801 | s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC); |
| 4784 | 4802 | ||
| 4803 | if (FD_SETSIZE <= s) | ||
| 4804 | { | ||
| 4805 | emacs_close (s); | ||
| 4806 | s = -1; | ||
| 4807 | errno = EMFILE; | ||
| 4808 | } | ||
| 4809 | |||
| 4785 | if (s < 0) | 4810 | if (s < 0) |
| 4786 | { | 4811 | { |
| 4787 | int code = errno; | 4812 | int code = errno; |