diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/callproc.c | 86 |
2 files changed, 59 insertions, 38 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index efa404afc2f..da15a612a19 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2012-11-28 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | * callproc.c (Fcall_process): Fix vfork portability problems. | ||
| 4 | Do not assume that fd[0], count, filefd, and save_environ survive | ||
| 5 | vfork. Fix bug whereby wrong errno value could be reported for | ||
| 6 | pipe failure. Some minor cleanups, too, as follows. Move buf and | ||
| 7 | bufsize to the context where they're needed. Change new_argv to | ||
| 8 | be of type char **, as this is more convenient and avoids casts. | ||
| 9 | (CALLPROC_BUFFER_SIZE_MIN, CALLPROC_BUFFER_SIZE_MAX): | ||
| 10 | Now local constants, not macros. | ||
| 11 | |||
| 1 | 2012-11-18 Kenichi Handa <handa@gnu.org> | 12 | 2012-11-18 Kenichi Handa <handa@gnu.org> |
| 2 | 13 | ||
| 3 | * font.c (font_unparse_xlfd): Fix previous change. Keep "const" | 14 | * font.c (font_unparse_xlfd): Fix previous change. Keep "const" |
diff --git a/src/callproc.c b/src/callproc.c index c9a504746b3..bba1c043b4c 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -183,16 +183,11 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 183 | { | 183 | { |
| 184 | Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail; | 184 | Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail; |
| 185 | bool display_p; | 185 | bool display_p; |
| 186 | int fd[2]; | 186 | int fd0, fd1, filefd; |
| 187 | int filefd; | ||
| 188 | #define CALLPROC_BUFFER_SIZE_MIN (16 * 1024) | ||
| 189 | #define CALLPROC_BUFFER_SIZE_MAX (4 * CALLPROC_BUFFER_SIZE_MIN) | ||
| 190 | char buf[CALLPROC_BUFFER_SIZE_MAX]; | ||
| 191 | int bufsize = CALLPROC_BUFFER_SIZE_MIN; | ||
| 192 | ptrdiff_t count = SPECPDL_INDEX (); | 187 | ptrdiff_t count = SPECPDL_INDEX (); |
| 193 | USE_SAFE_ALLOCA; | 188 | USE_SAFE_ALLOCA; |
| 194 | 189 | ||
| 195 | register const unsigned char **new_argv; | 190 | char **new_argv; |
| 196 | /* File to use for stderr in the child. | 191 | /* File to use for stderr in the child. |
| 197 | t means use same as standard output. */ | 192 | t means use same as standard output. */ |
| 198 | Lisp_Object error_file; | 193 | Lisp_Object error_file; |
| @@ -432,12 +427,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 432 | } | 427 | } |
| 433 | UNGCPRO; | 428 | UNGCPRO; |
| 434 | for (i = 4; i < nargs; i++) | 429 | for (i = 4; i < nargs; i++) |
| 435 | new_argv[i - 3] = SDATA (args[i]); | 430 | new_argv[i - 3] = SSDATA (args[i]); |
| 436 | new_argv[i - 3] = 0; | 431 | new_argv[i - 3] = 0; |
| 437 | } | 432 | } |
| 438 | else | 433 | else |
| 439 | new_argv[1] = 0; | 434 | new_argv[1] = 0; |
| 440 | new_argv[0] = SDATA (path); | 435 | new_argv[0] = SSDATA (path); |
| 441 | 436 | ||
| 442 | #ifdef MSDOS /* MW, July 1993 */ | 437 | #ifdef MSDOS /* MW, July 1993 */ |
| 443 | 438 | ||
| @@ -466,29 +461,35 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 466 | } | 461 | } |
| 467 | else | 462 | else |
| 468 | outfilefd = fd_output; | 463 | outfilefd = fd_output; |
| 469 | fd[0] = filefd; | 464 | fd0 = filefd; |
| 470 | fd[1] = outfilefd; | 465 | fd1 = outfilefd; |
| 471 | #endif /* MSDOS */ | 466 | #endif /* MSDOS */ |
| 472 | 467 | ||
| 473 | if (INTEGERP (buffer)) | 468 | if (INTEGERP (buffer)) |
| 474 | fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1; | 469 | { |
| 470 | fd0 = -1; | ||
| 471 | fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0); | ||
| 472 | } | ||
| 475 | else | 473 | else |
| 476 | { | 474 | { |
| 477 | #ifndef MSDOS | 475 | #ifndef MSDOS |
| 478 | errno = 0; | 476 | int fd[2]; |
| 479 | if (pipe (fd) == -1) | 477 | if (pipe (fd) == -1) |
| 480 | { | 478 | { |
| 479 | int pipe_errno = errno; | ||
| 481 | emacs_close (filefd); | 480 | emacs_close (filefd); |
| 481 | errno = pipe_errno; | ||
| 482 | report_file_error ("Creating process pipe", Qnil); | 482 | report_file_error ("Creating process pipe", Qnil); |
| 483 | } | 483 | } |
| 484 | fd0 = fd[0]; | ||
| 485 | fd1 = fd[1]; | ||
| 484 | #endif | 486 | #endif |
| 485 | } | 487 | } |
| 486 | 488 | ||
| 487 | { | 489 | { |
| 488 | /* child_setup must clobber environ in systems with true vfork. | 490 | /* child_setup must clobber environ in systems with true vfork. |
| 489 | Protect it from permanent change. */ | 491 | Protect it from permanent change. */ |
| 490 | register char **save_environ = environ; | 492 | char **save_environ = environ; |
| 491 | register int fd1 = fd[1]; | ||
| 492 | int fd_error = fd1; | 493 | int fd_error = fd1; |
| 493 | 494 | ||
| 494 | if (fd_output >= 0) | 495 | if (fd_output >= 0) |
| @@ -520,8 +521,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 520 | if (fd_error < 0) | 521 | if (fd_error < 0) |
| 521 | { | 522 | { |
| 522 | emacs_close (filefd); | 523 | emacs_close (filefd); |
| 523 | if (fd[0] != filefd) | 524 | if (fd0 != filefd) |
| 524 | emacs_close (fd[0]); | 525 | emacs_close (fd0); |
| 525 | if (fd1 >= 0) | 526 | if (fd1 >= 0) |
| 526 | emacs_close (fd1); | 527 | emacs_close (fd1); |
| 527 | #ifdef MSDOS | 528 | #ifdef MSDOS |
| @@ -538,8 +539,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 538 | /* Note that on MSDOS `child_setup' actually returns the child process | 539 | /* Note that on MSDOS `child_setup' actually returns the child process |
| 539 | exit status, not its PID, so we assign it to `synch_process_retcode' | 540 | exit status, not its PID, so we assign it to `synch_process_retcode' |
| 540 | below. */ | 541 | below. */ |
| 541 | pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv, | 542 | pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir); |
| 542 | 0, current_dir); | ||
| 543 | 543 | ||
| 544 | /* Record that the synchronous process exited and note its | 544 | /* Record that the synchronous process exited and note its |
| 545 | termination status. */ | 545 | termination status. */ |
| @@ -559,8 +559,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 559 | { | 559 | { |
| 560 | /* Since CRLF is converted to LF within `decode_coding', we | 560 | /* Since CRLF is converted to LF within `decode_coding', we |
| 561 | can always open a file with binary mode. */ | 561 | can always open a file with binary mode. */ |
| 562 | fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); | 562 | fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); |
| 563 | if (fd[0] < 0) | 563 | if (fd0 < 0) |
| 564 | { | 564 | { |
| 565 | unlink (tempfile); | 565 | unlink (tempfile); |
| 566 | emacs_close (filefd); | 566 | emacs_close (filefd); |
| @@ -569,11 +569,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 569 | } | 569 | } |
| 570 | } | 570 | } |
| 571 | else | 571 | else |
| 572 | fd[0] = -1; /* We are not going to read from tempfile. */ | 572 | fd0 = -1; /* We are not going to read from tempfile. */ |
| 573 | #else /* not MSDOS */ | 573 | #else /* not MSDOS */ |
| 574 | #ifdef WINDOWSNT | 574 | #ifdef WINDOWSNT |
| 575 | pid = child_setup (filefd, fd1, fd_error, (char **) new_argv, | 575 | pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); |
| 576 | 0, current_dir); | ||
| 577 | #else /* not WINDOWSNT */ | 576 | #else /* not WINDOWSNT */ |
| 578 | 577 | ||
| 579 | block_input (); | 578 | block_input (); |
| @@ -586,11 +585,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 586 | bool volatile display_p_volatile = display_p; | 585 | bool volatile display_p_volatile = display_p; |
| 587 | bool volatile output_to_buffer_volatile = output_to_buffer; | 586 | bool volatile output_to_buffer_volatile = output_to_buffer; |
| 588 | bool volatile sa_must_free_volatile = sa_must_free; | 587 | bool volatile sa_must_free_volatile = sa_must_free; |
| 588 | int volatile fd0_volatile = fd0; | ||
| 589 | int volatile fd1_volatile = fd1; | 589 | int volatile fd1_volatile = fd1; |
| 590 | int volatile fd_error_volatile = fd_error; | 590 | int volatile fd_error_volatile = fd_error; |
| 591 | int volatile fd_output_volatile = fd_output; | 591 | int volatile fd_output_volatile = fd_output; |
| 592 | int volatile filefd_volatile = filefd; | ||
| 593 | ptrdiff_t volatile count_volatile = count; | ||
| 592 | ptrdiff_t volatile sa_count_volatile = sa_count; | 594 | ptrdiff_t volatile sa_count_volatile = sa_count; |
| 593 | unsigned char const **volatile new_argv_volatile = new_argv; | 595 | char **volatile new_argv_volatile = new_argv; |
| 596 | char **volatile new_save_environ = save_environ; | ||
| 594 | 597 | ||
| 595 | pid = vfork (); | 598 | pid = vfork (); |
| 596 | 599 | ||
| @@ -598,27 +601,30 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 598 | coding_systems = coding_systems_volatile; | 601 | coding_systems = coding_systems_volatile; |
| 599 | current_dir = current_dir_volatile; | 602 | current_dir = current_dir_volatile; |
| 600 | display_p = display_p_volatile; | 603 | display_p = display_p_volatile; |
| 604 | output_to_buffer = output_to_buffer_volatile; | ||
| 605 | sa_must_free = sa_must_free_volatile; | ||
| 606 | fd0 = fd0_volatile; | ||
| 601 | fd1 = fd1_volatile; | 607 | fd1 = fd1_volatile; |
| 602 | fd_error = fd_error_volatile; | 608 | fd_error = fd_error_volatile; |
| 603 | fd_output = fd_output_volatile; | 609 | fd_output = fd_output_volatile; |
| 604 | output_to_buffer = output_to_buffer_volatile; | 610 | filefd = filefd_volatile; |
| 605 | sa_must_free = sa_must_free_volatile; | 611 | count = count_volatile; |
| 606 | sa_count = sa_count_volatile; | 612 | sa_count = sa_count_volatile; |
| 607 | new_argv = new_argv_volatile; | 613 | new_argv = new_argv_volatile; |
| 614 | save_environ = new_save_environ; | ||
| 608 | } | 615 | } |
| 609 | 616 | ||
| 610 | if (pid == 0) | 617 | if (pid == 0) |
| 611 | { | 618 | { |
| 612 | if (fd[0] >= 0) | 619 | if (fd0 >= 0) |
| 613 | emacs_close (fd[0]); | 620 | emacs_close (fd0); |
| 614 | 621 | ||
| 615 | setsid (); | 622 | setsid (); |
| 616 | 623 | ||
| 617 | /* Emacs ignores SIGPIPE, but the child should not. */ | 624 | /* Emacs ignores SIGPIPE, but the child should not. */ |
| 618 | signal (SIGPIPE, SIG_DFL); | 625 | signal (SIGPIPE, SIG_DFL); |
| 619 | 626 | ||
| 620 | child_setup (filefd, fd1, fd_error, (char **) new_argv, | 627 | child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); |
| 621 | 0, current_dir); | ||
| 622 | } | 628 | } |
| 623 | 629 | ||
| 624 | unblock_input (); | 630 | unblock_input (); |
| @@ -632,7 +638,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 632 | 638 | ||
| 633 | environ = save_environ; | 639 | environ = save_environ; |
| 634 | 640 | ||
| 635 | /* Close most of our fd's, but not fd[0] | 641 | /* Close most of our file descriptors, but not fd0 |
| 636 | since we will use that to read input from. */ | 642 | since we will use that to read input from. */ |
| 637 | emacs_close (filefd); | 643 | emacs_close (filefd); |
| 638 | if (fd_output >= 0) | 644 | if (fd_output >= 0) |
| @@ -643,15 +649,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 643 | 649 | ||
| 644 | if (pid < 0) | 650 | if (pid < 0) |
| 645 | { | 651 | { |
| 646 | if (fd[0] >= 0) | 652 | if (fd0 >= 0) |
| 647 | emacs_close (fd[0]); | 653 | emacs_close (fd0); |
| 648 | report_file_error ("Doing vfork", Qnil); | 654 | report_file_error ("Doing vfork", Qnil); |
| 649 | } | 655 | } |
| 650 | 656 | ||
| 651 | if (INTEGERP (buffer)) | 657 | if (INTEGERP (buffer)) |
| 652 | { | 658 | { |
| 653 | if (fd[0] >= 0) | 659 | if (fd0 >= 0) |
| 654 | emacs_close (fd[0]); | 660 | emacs_close (fd0); |
| 655 | return Qnil; | 661 | return Qnil; |
| 656 | } | 662 | } |
| 657 | 663 | ||
| @@ -666,7 +672,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 666 | #endif /* not MSDOS */ | 672 | #endif /* not MSDOS */ |
| 667 | record_unwind_protect (call_process_cleanup, | 673 | record_unwind_protect (call_process_cleanup, |
| 668 | Fcons (Fcurrent_buffer (), | 674 | Fcons (Fcurrent_buffer (), |
| 669 | Fcons (INTEGER_TO_CONS (fd[0]), | 675 | Fcons (INTEGER_TO_CONS (fd0), |
| 670 | cleanup_info_tail))); | 676 | cleanup_info_tail))); |
| 671 | 677 | ||
| 672 | if (BUFFERP (buffer)) | 678 | if (BUFFERP (buffer)) |
| @@ -723,6 +729,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 723 | 729 | ||
| 724 | if (output_to_buffer) | 730 | if (output_to_buffer) |
| 725 | { | 731 | { |
| 732 | enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 }; | ||
| 733 | enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN }; | ||
| 734 | char buf[CALLPROC_BUFFER_SIZE_MAX]; | ||
| 735 | int bufsize = CALLPROC_BUFFER_SIZE_MIN; | ||
| 726 | int nread; | 736 | int nread; |
| 727 | bool first = 1; | 737 | bool first = 1; |
| 728 | EMACS_INT total_read = 0; | 738 | EMACS_INT total_read = 0; |
| @@ -739,7 +749,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 739 | nread = carryover; | 749 | nread = carryover; |
| 740 | while (nread < bufsize - 1024) | 750 | while (nread < bufsize - 1024) |
| 741 | { | 751 | { |
| 742 | int this_read = emacs_read (fd[0], buf + nread, | 752 | int this_read = emacs_read (fd0, buf + nread, |
| 743 | bufsize - nread); | 753 | bufsize - nread); |
| 744 | 754 | ||
| 745 | if (this_read < 0) | 755 | if (this_read < 0) |