diff options
| author | Paul Eggert | 2012-10-31 10:27:29 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-10-31 10:27:29 -0700 |
| commit | 322aea6ddf7ec7fd71410d98ec1de69f219aff3e (patch) | |
| tree | 5efe99d41566350e9793015cde6ebb656e1278e6 /src | |
| parent | 220cb2bd70c65041417554cc2dc10edb4a53de5c (diff) | |
| download | emacs-322aea6ddf7ec7fd71410d98ec1de69f219aff3e.tar.gz emacs-322aea6ddf7ec7fd71410d98ec1de69f219aff3e.zip | |
Fix crash when using Emacs as commit editor for git.
* callproc.c (setpgrp): Remove macro, as we now use setpgid
and it is configured in conf_post.h.
(Fcall_process): Don't invoke both setsid and setpgid; the former
is enough, if it exists.
* callproc.c (Fcall_process, child_setup):
* process.c (create_process): Use setpgid.
* conf_post.h (setpgid) [!HAVE_SETPGID]: New macro, which substitutes
for the real thing.
* dispnew.c (init_display): Initialize the foreground group
if we are running a tty display.
* emacs.c (main): Do not worry about setpgrp; init_display does it now.
* lisp.h (init_foreground_group): New decl.
* sysdep.c (inherited_pgroup): New static var.
(init_foreground_group, tcsetpgrp_without_stopping)
(narrow_foreground_group, widen_foreground_group): New functions.
(init_sys_modes): Narrow foreground group.
(reset_sys_modes): Widen foreground group.
Fixes: debbugs:12697
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 21 | ||||
| -rw-r--r-- | src/callproc.c | 23 | ||||
| -rw-r--r-- | src/conf_post.h | 8 | ||||
| -rw-r--r-- | src/dispnew.c | 2 | ||||
| -rw-r--r-- | src/emacs.c | 13 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/process.c | 10 | ||||
| -rw-r--r-- | src/sysdep.c | 72 |
8 files changed, 115 insertions, 35 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4edb3a7007b..4dc18b6909b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,24 @@ | |||
| 1 | 2012-10-31 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix crash when using Emacs as commit editor for git (Bug#12697). | ||
| 4 | * callproc.c (setpgrp): Remove macro, as we now use setpgid | ||
| 5 | and it is configured in conf_post.h. | ||
| 6 | (Fcall_process): Don't invoke both setsid and setpgid; the former | ||
| 7 | is enough, if it exists. | ||
| 8 | * callproc.c (Fcall_process, child_setup): | ||
| 9 | * process.c (create_process): Use setpgid. | ||
| 10 | * conf_post.h (setpgid) [!HAVE_SETPGID]: New macro, which substitutes | ||
| 11 | for the real thing. | ||
| 12 | * dispnew.c (init_display): Initialize the foreground group | ||
| 13 | if we are running a tty display. | ||
| 14 | * emacs.c (main): Do not worry about setpgrp; init_display does it now. | ||
| 15 | * lisp.h (init_foreground_group): New decl. | ||
| 16 | * sysdep.c (inherited_pgroup): New static var. | ||
| 17 | (init_foreground_group, tcsetpgrp_without_stopping) | ||
| 18 | (narrow_foreground_group, widen_foreground_group): New functions. | ||
| 19 | (init_sys_modes): Narrow foreground group. | ||
| 20 | (reset_sys_modes): Widen foreground group. | ||
| 21 | |||
| 1 | 2012-10-31 Michael Albinus <michael.albinus@gmx.de> | 22 | 2012-10-31 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 23 | ||
| 3 | * dbusbind.c: Fix cut'n'waste error. Use HAVE_DBUS_VALIDATE_INTERFACE. | 24 | * dbusbind.c: Fix cut'n'waste error. Use HAVE_DBUS_VALIDATE_INTERFACE. |
diff --git a/src/callproc.c b/src/callproc.c index b33882e54c2..c236f22fc86 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -64,13 +64,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 64 | #include "nsterm.h" | 64 | #include "nsterm.h" |
| 65 | #endif | 65 | #endif |
| 66 | 66 | ||
| 67 | #ifdef HAVE_SETPGID | ||
| 68 | #if !defined (USG) | ||
| 69 | #undef setpgrp | ||
| 70 | #define setpgrp setpgid | ||
| 71 | #endif | ||
| 72 | #endif | ||
| 73 | |||
| 74 | /* Pattern used by call-process-region to make temp files. */ | 67 | /* Pattern used by call-process-region to make temp files. */ |
| 75 | static Lisp_Object Vtemp_file_name_pattern; | 68 | static Lisp_Object Vtemp_file_name_pattern; |
| 76 | 69 | ||
| @@ -618,14 +611,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 618 | { | 611 | { |
| 619 | if (fd[0] >= 0) | 612 | if (fd[0] >= 0) |
| 620 | emacs_close (fd[0]); | 613 | emacs_close (fd[0]); |
| 614 | |||
| 621 | #ifdef HAVE_SETSID | 615 | #ifdef HAVE_SETSID |
| 622 | setsid (); | 616 | setsid (); |
| 623 | #endif | ||
| 624 | #if defined (USG) | ||
| 625 | setpgrp (); | ||
| 626 | #else | 617 | #else |
| 627 | setpgrp (pid, pid); | 618 | setpgid (0, 0); |
| 628 | #endif /* USG */ | 619 | #endif |
| 629 | 620 | ||
| 630 | /* Emacs ignores SIGPIPE, but the child should not. */ | 621 | /* Emacs ignores SIGPIPE, but the child should not. */ |
| 631 | signal (SIGPIPE, SIG_DFL); | 622 | signal (SIGPIPE, SIG_DFL); |
| @@ -1295,13 +1286,9 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1295 | if (err != in && err != out) | 1286 | if (err != in && err != out) |
| 1296 | emacs_close (err); | 1287 | emacs_close (err); |
| 1297 | 1288 | ||
| 1298 | #if defined (USG) | 1289 | #if defined HAVE_SETPGID || ! (defined USG && defined SETPGRP_RELEASES_CTTY) |
| 1299 | #ifndef SETPGRP_RELEASES_CTTY | 1290 | setpgid (pid, pid); |
| 1300 | setpgrp (); /* No arguments but equivalent in this case */ | ||
| 1301 | #endif | 1291 | #endif |
| 1302 | #else /* not USG */ | ||
| 1303 | setpgrp (pid, pid); | ||
| 1304 | #endif /* not USG */ | ||
| 1305 | 1292 | ||
| 1306 | /* setpgrp_of_tty is incorrect here; it uses input_fd. */ | 1293 | /* setpgrp_of_tty is incorrect here; it uses input_fd. */ |
| 1307 | tcsetpgrp (0, pid); | 1294 | tcsetpgrp (0, pid); |
diff --git a/src/conf_post.h b/src/conf_post.h index aa008107ba6..6056821d4a7 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -112,6 +112,14 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */ | |||
| 112 | #endif | 112 | #endif |
| 113 | /* End of gnulib-related stuff. */ | 113 | /* End of gnulib-related stuff. */ |
| 114 | 114 | ||
| 115 | #ifndef HAVE_SETPGID | ||
| 116 | # ifdef USG | ||
| 117 | # define setpgid(pid, pgid) setpgrp () | ||
| 118 | # else | ||
| 119 | # define setpgid(pid, pgid) setpgrp (pid, pgid) | ||
| 120 | # endif | ||
| 121 | #endif | ||
| 122 | |||
| 115 | /* Define one of these for easier conditionals. */ | 123 | /* Define one of these for easier conditionals. */ |
| 116 | #ifdef HAVE_X_WINDOWS | 124 | #ifdef HAVE_X_WINDOWS |
| 117 | /* We need a little extra space, see ../../lisp/loadup.el and the | 125 | /* We need a little extra space, see ../../lisp/loadup.el and the |
diff --git a/src/dispnew.c b/src/dispnew.c index fa24408aa43..9f0e22fcdcb 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -6283,6 +6283,8 @@ init_display (void) | |||
| 6283 | struct terminal *t; | 6283 | struct terminal *t; |
| 6284 | struct frame *f = XFRAME (selected_frame); | 6284 | struct frame *f = XFRAME (selected_frame); |
| 6285 | 6285 | ||
| 6286 | init_foreground_group (); | ||
| 6287 | |||
| 6286 | /* Open a display on the controlling tty. */ | 6288 | /* Open a display on the controlling tty. */ |
| 6287 | t = init_tty (0, terminal_type, 1); /* Errors are fatal. */ | 6289 | t = init_tty (0, terminal_type, 1); /* Errors are fatal. */ |
| 6288 | 6290 | ||
diff --git a/src/emacs.c b/src/emacs.c index 7f3228641ae..98e3f11f0cb 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1091,19 +1091,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1091 | #endif /* DOS_NT */ | 1091 | #endif /* DOS_NT */ |
| 1092 | } | 1092 | } |
| 1093 | 1093 | ||
| 1094 | #if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC) | ||
| 1094 | if (! noninteractive) | 1095 | if (! noninteractive) |
| 1095 | { | 1096 | { |
| 1096 | #if defined (USG5) && defined (INTERRUPT_INPUT) | 1097 | extern void malloc_enable_thread (void); |
| 1097 | setpgrp (); | ||
| 1098 | #endif | ||
| 1099 | #if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC) | ||
| 1100 | { | ||
| 1101 | extern void malloc_enable_thread (void); | ||
| 1102 | 1098 | ||
| 1103 | malloc_enable_thread (); | 1099 | malloc_enable_thread (); |
| 1104 | } | ||
| 1105 | #endif | ||
| 1106 | } | 1100 | } |
| 1101 | #endif | ||
| 1107 | 1102 | ||
| 1108 | init_signals (dumping); | 1103 | init_signals (dumping); |
| 1109 | 1104 | ||
diff --git a/src/lisp.h b/src/lisp.h index 4cf8fef0de3..3ec188b67c7 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3474,6 +3474,7 @@ struct terminal; | |||
| 3474 | extern char *get_current_dir_name (void); | 3474 | extern char *get_current_dir_name (void); |
| 3475 | #endif | 3475 | #endif |
| 3476 | extern void stuff_char (char c); | 3476 | extern void stuff_char (char c); |
| 3477 | extern void init_foreground_group (void); | ||
| 3477 | extern void init_sigio (int); | 3478 | extern void init_sigio (int); |
| 3478 | extern void sys_subshell (void); | 3479 | extern void sys_subshell (void); |
| 3479 | extern void sys_suspend (void); | 3480 | extern void sys_suspend (void); |
diff --git a/src/process.c b/src/process.c index 307e82819d6..77e99ead01f 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1759,12 +1759,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1759 | #endif | 1759 | #endif |
| 1760 | } | 1760 | } |
| 1761 | #else /* not HAVE_SETSID */ | 1761 | #else /* not HAVE_SETSID */ |
| 1762 | #ifdef USG | 1762 | /* It's very important to call setpgid here and no time |
| 1763 | /* It's very important to call setpgrp here and no time | ||
| 1764 | afterwards. Otherwise, we lose our controlling tty which | 1763 | afterwards. Otherwise, we lose our controlling tty which |
| 1765 | is set when we open the pty. */ | 1764 | is set when we open the pty. */ |
| 1766 | setpgrp (); | 1765 | setpgid (0, 0); |
| 1767 | #endif /* USG */ | ||
| 1768 | #endif /* not HAVE_SETSID */ | 1766 | #endif /* not HAVE_SETSID */ |
| 1769 | #if defined (LDISC1) | 1767 | #if defined (LDISC1) |
| 1770 | if (pty_flag && xforkin >= 0) | 1768 | if (pty_flag && xforkin >= 0) |
| @@ -1802,11 +1800,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1802 | /* In order to get a controlling terminal on some versions | 1800 | /* In order to get a controlling terminal on some versions |
| 1803 | of BSD, it is necessary to put the process in pgrp 0 | 1801 | of BSD, it is necessary to put the process in pgrp 0 |
| 1804 | before it opens the terminal. */ | 1802 | before it opens the terminal. */ |
| 1805 | #ifdef HAVE_SETPGID | ||
| 1806 | setpgid (0, 0); | 1803 | setpgid (0, 0); |
| 1807 | #else | ||
| 1808 | setpgrp (0, 0); | ||
| 1809 | #endif | ||
| 1810 | #endif | 1804 | #endif |
| 1811 | } | 1805 | } |
| 1812 | #endif /* TIOCNOTTY */ | 1806 | #endif /* TIOCNOTTY */ |
diff --git a/src/sysdep.c b/src/sysdep.c index c7174e91612..63eac5d9e09 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -683,6 +683,75 @@ ignore_sigio (void) | |||
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | 685 | ||
| 686 | /* Saving and restoring the process group of Emacs's terminal. */ | ||
| 687 | |||
| 688 | /* The process group of which Emacs was a member when it initially | ||
| 689 | started. | ||
| 690 | |||
| 691 | If Emacs was in its own process group (i.e. inherited_pgroup == | ||
| 692 | getpid ()), then we know we're running under a shell with job | ||
| 693 | control (Emacs would never be run as part of a pipeline). | ||
| 694 | Everything is fine. | ||
| 695 | |||
| 696 | If Emacs was not in its own process group, then we know we're | ||
| 697 | running under a shell (or a caller) that doesn't know how to | ||
| 698 | separate itself from Emacs (like sh). Emacs must be in its own | ||
| 699 | process group in order to receive SIGIO correctly. In this | ||
| 700 | situation, we put ourselves in our own pgroup, forcibly set the | ||
| 701 | tty's pgroup to our pgroup, and make sure to restore and reinstate | ||
| 702 | the tty's pgroup just like any other terminal setting. If | ||
| 703 | inherited_group was not the tty's pgroup, then we'll get a | ||
| 704 | SIGTTmumble when we try to change the tty's pgroup, and a CONT if | ||
| 705 | it goes foreground in the future, which is what should happen. */ | ||
| 706 | |||
| 707 | static pid_t inherited_pgroup; | ||
| 708 | |||
| 709 | void | ||
| 710 | init_foreground_group (void) | ||
| 711 | { | ||
| 712 | pid_t pgrp = EMACS_GETPGRP (0); | ||
| 713 | inherited_pgroup = getpid () == pgrp ? 0 : pgrp; | ||
| 714 | } | ||
| 715 | |||
| 716 | /* Safely set a controlling terminal FD's process group to PGID. | ||
| 717 | If we are not in the foreground already, POSIX requires tcsetpgrp | ||
| 718 | to deliver a SIGTTOU signal, which would stop us. This is an | ||
| 719 | annoyance, so temporarily ignore the signal. | ||
| 720 | |||
| 721 | In practice, platforms lacking SIGTTOU also lack tcsetpgrp, so | ||
| 722 | skip all this unless SIGTTOU is defined. */ | ||
| 723 | static void | ||
| 724 | tcsetpgrp_without_stopping (int fd, pid_t pgid) | ||
| 725 | { | ||
| 726 | #ifdef SIGTTOU | ||
| 727 | signal_handler_t handler; | ||
| 728 | block_input (); | ||
| 729 | handler = signal (SIGTTOU, SIG_IGN); | ||
| 730 | tcsetpgrp (fd, pgid); | ||
| 731 | signal (SIGTTOU, handler); | ||
| 732 | unblock_input (); | ||
| 733 | #endif | ||
| 734 | } | ||
| 735 | |||
| 736 | /* Split off the foreground process group to Emacs alone. When we are | ||
| 737 | in the foreground, but not started in our own process group, | ||
| 738 | redirect the tty device handle FD to point to our own process | ||
| 739 | group. FD must be the file descriptor of the controlling tty. */ | ||
| 740 | static void | ||
| 741 | narrow_foreground_group (int fd) | ||
| 742 | { | ||
| 743 | if (inherited_pgroup && setpgid (0, 0) == 0) | ||
| 744 | tcsetpgrp_without_stopping (fd, getpid ()); | ||
| 745 | } | ||
| 746 | |||
| 747 | /* Set the tty to our original foreground group. */ | ||
| 748 | static void | ||
| 749 | widen_foreground_group (int fd) | ||
| 750 | { | ||
| 751 | if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0) | ||
| 752 | tcsetpgrp_without_stopping (fd, inherited_pgroup); | ||
| 753 | } | ||
| 754 | |||
| 686 | /* Getting and setting emacs_tty structures. */ | 755 | /* Getting and setting emacs_tty structures. */ |
| 687 | 756 | ||
| 688 | /* Set *TC to the parameters associated with the terminal FD. | 757 | /* Set *TC to the parameters associated with the terminal FD. |
| @@ -799,6 +868,8 @@ init_sys_modes (struct tty_display_info *tty_out) | |||
| 799 | if (!tty_out->output) | 868 | if (!tty_out->output) |
| 800 | return; /* The tty is suspended. */ | 869 | return; /* The tty is suspended. */ |
| 801 | 870 | ||
| 871 | narrow_foreground_group (fileno (tty_out->input)); | ||
| 872 | |||
| 802 | if (! tty_out->old_tty) | 873 | if (! tty_out->old_tty) |
| 803 | tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty); | 874 | tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty); |
| 804 | 875 | ||
| @@ -1231,6 +1302,7 @@ reset_sys_modes (struct tty_display_info *tty_out) | |||
| 1231 | dos_ttcooked (); | 1302 | dos_ttcooked (); |
| 1232 | #endif | 1303 | #endif |
| 1233 | 1304 | ||
| 1305 | widen_foreground_group (fileno (tty_out->input)); | ||
| 1234 | } | 1306 | } |
| 1235 | 1307 | ||
| 1236 | #ifdef HAVE_PTYS | 1308 | #ifdef HAVE_PTYS |