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 /test/src/process-tests.el | |
| 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 'test/src/process-tests.el')
| -rw-r--r-- | test/src/process-tests.el | 100 |
1 files changed, 71 insertions, 29 deletions
diff --git a/test/src/process-tests.el b/test/src/process-tests.el index 590f72f9b03..eee8636067c 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el | |||
| @@ -426,11 +426,52 @@ add some process objects to VAR." | |||
| 426 | ,(macroexp-progn body) | 426 | ,(macroexp-progn body) |
| 427 | (mapc #'delete-process ,var)))) | 427 | (mapc #'delete-process ,var)))) |
| 428 | 428 | ||
| 429 | (defmacro process-tests--with-many-pipes (&rest body) | 429 | (defmacro process-tests--with-raised-rlimit (&rest body) |
| 430 | "Generate lots of pipe processes. | 430 | "Evaluate BODY using a higher limit for the number of open files. |
| 431 | Attempt to set the resource limit for the number of open files | ||
| 432 | temporarily to the highest possible value." | ||
| 433 | (declare (indent 0) (debug t)) | ||
| 434 | (let ((prlimit (make-symbol "prlimit")) | ||
| 435 | (soft (make-symbol "soft")) | ||
| 436 | (hard (make-symbol "hard")) | ||
| 437 | (pid-arg (make-symbol "pid-arg"))) | ||
| 438 | `(let ((,prlimit (executable-find "prlimit")) | ||
| 439 | (,pid-arg (format "--pid=%d" (emacs-pid))) | ||
| 440 | (,soft nil) (,hard nil)) | ||
| 441 | (cl-flet ((set-limit | ||
| 442 | (value) | ||
| 443 | (cl-check-type value natnum) | ||
| 444 | (when ,prlimit | ||
| 445 | (call-process ,prlimit nil nil nil | ||
| 446 | ,pid-arg | ||
| 447 | (format "--nofile=%d:" value))))) | ||
| 448 | (when ,prlimit | ||
| 449 | (with-temp-buffer | ||
| 450 | (when (eql (call-process ,prlimit nil t nil | ||
| 451 | ,pid-arg "--nofile" | ||
| 452 | "--raw" "--noheadings" | ||
| 453 | "--output=SOFT,HARD") | ||
| 454 | 0) | ||
| 455 | (goto-char (point-min)) | ||
| 456 | (when (looking-at (rx (group (+ digit)) (+ blank) | ||
| 457 | (group (+ digit)) ?\n)) | ||
| 458 | (setq ,soft (string-to-number | ||
| 459 | (match-string-no-properties 1)) | ||
| 460 | ,hard (string-to-number | ||
| 461 | (match-string-no-properties 2)))))) | ||
| 462 | (and ,soft ,hard (< ,soft ,hard) | ||
| 463 | (set-limit ,hard))) | ||
| 464 | (unwind-protect | ||
| 465 | ,(macroexp-progn body) | ||
| 466 | (when ,soft (set-limit ,soft))))))) | ||
| 467 | |||
| 468 | (defmacro process-tests--fd-setsize-test (&rest body) | ||
| 469 | "Run BODY as a test for FD_SETSIZE overflow. | ||
| 431 | Try to generate pipe processes until we are close to the | 470 | Try to generate pipe processes until we are close to the |
| 432 | FD_SETSIZE limit. Within BODY, only a small number of file | 471 | FD_SETSIZE limit. Within BODY, only a small number of file |
| 433 | descriptors should still be available." | 472 | descriptors should still be available. Furthermore, raise the |
| 473 | maximum number of open files in the Emacs process above | ||
| 474 | FD_SETSIZE." | ||
| 434 | (declare (indent 0) (debug t)) | 475 | (declare (indent 0) (debug t)) |
| 435 | (let ((process (make-symbol "process")) | 476 | (let ((process (make-symbol "process")) |
| 436 | (processes (make-symbol "processes")) | 477 | (processes (make-symbol "processes")) |
| @@ -440,28 +481,29 @@ descriptors should still be available." | |||
| 440 | ;; MS-Windows we artificially limit FD_SETSIZE to 64, see the | 481 | ;; MS-Windows we artificially limit FD_SETSIZE to 64, see the |
| 441 | ;; commentary in w32proc.c. | 482 | ;; commentary in w32proc.c. |
| 442 | (fd-setsize (if (eq system-type 'windows-nt) 64 1024))) | 483 | (fd-setsize (if (eq system-type 'windows-nt) 64 1024))) |
| 443 | `(process-tests--with-buffers ,buffers | 484 | `(process-tests--with-raised-rlimit |
| 444 | (process-tests--with-processes ,processes | 485 | (process-tests--with-buffers ,buffers |
| 445 | ;; First, allocate enough pipes to definitely exceed the | 486 | (process-tests--with-processes ,processes |
| 446 | ;; FD_SETSIZE limit. | 487 | ;; First, allocate enough pipes to definitely exceed the |
| 447 | (cl-loop for i from 1 to ,(1+ fd-setsize) | 488 | ;; FD_SETSIZE limit. |
| 448 | for ,buffer = (generate-new-buffer | 489 | (cl-loop for i from 1 to ,(1+ fd-setsize) |
| 449 | (format " *pipe %d*" i)) | 490 | for ,buffer = (generate-new-buffer |
| 450 | do (push ,buffer ,buffers) | 491 | (format " *pipe %d*" i)) |
| 451 | for ,process = (process-tests--ignore-EMFILE | 492 | do (push ,buffer ,buffers) |
| 452 | (make-pipe-process | 493 | for ,process = (process-tests--ignore-EMFILE |
| 453 | :name (format "pipe %d" i) | 494 | (make-pipe-process |
| 454 | :buffer ,buffer | 495 | :name (format "pipe %d" i) |
| 455 | :coding 'no-conversion | 496 | :buffer ,buffer |
| 456 | :noquery t)) | 497 | :coding 'no-conversion |
| 457 | while ,process | 498 | :noquery t)) |
| 458 | do (push ,process ,processes)) | 499 | while ,process |
| 459 | (unless (cddr ,processes) | 500 | do (push ,process ,processes)) |
| 460 | (ert-fail "Couldn't allocate enough pipes")) | 501 | (unless (cddr ,processes) |
| 461 | ;; Delete two pipes to test more edge cases. | 502 | (ert-fail "Couldn't allocate enough pipes")) |
| 462 | (delete-process (pop ,processes)) | 503 | ;; Delete two pipes to test more edge cases. |
| 463 | (delete-process (pop ,processes)) | 504 | (delete-process (pop ,processes)) |
| 464 | ,@body)))) | 505 | (delete-process (pop ,processes)) |
| 506 | ,@body))))) | ||
| 465 | 507 | ||
| 466 | (defmacro process-tests--with-temp-file (var &rest body) | 508 | (defmacro process-tests--with-temp-file (var &rest body) |
| 467 | "Bind VAR to the name of a new regular file and evaluate BODY. | 509 | "Bind VAR to the name of a new regular file and evaluate BODY. |
| @@ -502,7 +544,7 @@ FD_SETSIZE file descriptors (Bug#24325)." | |||
| 502 | (skip-unless sleep) | 544 | (skip-unless sleep) |
| 503 | (dolist (conn-type '(pipe pty)) | 545 | (dolist (conn-type '(pipe pty)) |
| 504 | (ert-info ((format "Connection type `%s'" conn-type)) | 546 | (ert-info ((format "Connection type `%s'" conn-type)) |
| 505 | (process-tests--with-many-pipes | 547 | (process-tests--fd-setsize-test |
| 506 | (process-tests--with-processes processes | 548 | (process-tests--with-processes processes |
| 507 | ;; Start processes until we exhaust the file descriptor | 549 | ;; Start processes until we exhaust the file descriptor |
| 508 | ;; set size. We assume that each process requires at | 550 | ;; set size. We assume that each process requires at |
| @@ -538,7 +580,7 @@ FD_SETSIZE file descriptors (Bug#24325)." | |||
| 538 | "Check that Emacs doesn't crash when trying to use more than | 580 | "Check that Emacs doesn't crash when trying to use more than |
| 539 | FD_SETSIZE file descriptors (Bug#24325)." | 581 | FD_SETSIZE file descriptors (Bug#24325)." |
| 540 | (with-timeout (60 (ert-fail "Test timed out")) | 582 | (with-timeout (60 (ert-fail "Test timed out")) |
| 541 | (process-tests--with-many-pipes | 583 | (process-tests--fd-setsize-test |
| 542 | (process-tests--with-buffers buffers | 584 | (process-tests--with-buffers buffers |
| 543 | (process-tests--with-processes processes | 585 | (process-tests--with-processes processes |
| 544 | ;; Start processes until we exhaust the file descriptor set | 586 | ;; Start processes until we exhaust the file descriptor set |
| @@ -580,7 +622,7 @@ FD_SETSIZE file descriptors (Bug#24325)." | |||
| 580 | :coding 'no-conversion | 622 | :coding 'no-conversion |
| 581 | :noquery t))) | 623 | :noquery t))) |
| 582 | (push server processes) | 624 | (push server processes) |
| 583 | (process-tests--with-many-pipes | 625 | (process-tests--fd-setsize-test |
| 584 | ;; Start processes until we exhaust the file descriptor | 626 | ;; Start processes until we exhaust the file descriptor |
| 585 | ;; set size. We assume that each process requires at | 627 | ;; set size. We assume that each process requires at |
| 586 | ;; least one file descriptor. | 628 | ;; least one file descriptor. |
| @@ -627,7 +669,7 @@ FD_SETSIZE file descriptors (Bug#24325)." | |||
| 627 | (should tty-name) | 669 | (should tty-name) |
| 628 | (should (file-exists-p tty-name)) | 670 | (should (file-exists-p tty-name)) |
| 629 | (push tty-name tty-names))) | 671 | (push tty-name tty-names))) |
| 630 | (process-tests--with-many-pipes | 672 | (process-tests--fd-setsize-test |
| 631 | (process-tests--with-processes processes | 673 | (process-tests--with-processes processes |
| 632 | (process-tests--with-buffers buffers | 674 | (process-tests--with-buffers buffers |
| 633 | (dolist (tty-name tty-names) | 675 | (dolist (tty-name tty-names) |