diff options
Diffstat (limited to 'src/w32proc.c')
| -rw-r--r-- | src/w32proc.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/src/w32proc.c b/src/w32proc.c index 26a0925ad87..b367b42d8c6 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -86,19 +86,34 @@ typedef void (_CALLBACK_ *signal_handler) (int); | |||
| 86 | /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ | 86 | /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ |
| 87 | static signal_handler sig_handlers[NSIG]; | 87 | static signal_handler sig_handlers[NSIG]; |
| 88 | 88 | ||
| 89 | /* Fake signal implementation to record the SIGCHLD handler. */ | 89 | /* Improve on the CRT 'signal' implementation so that we could record |
| 90 | the SIGCHLD handler. */ | ||
| 90 | signal_handler | 91 | signal_handler |
| 91 | sys_signal (int sig, signal_handler handler) | 92 | sys_signal (int sig, signal_handler handler) |
| 92 | { | 93 | { |
| 93 | signal_handler old; | 94 | signal_handler old; |
| 94 | 95 | ||
| 95 | if (sig != SIGCHLD) | 96 | /* SIGCHLD is needed for supporting subprocesses, see sys_kill |
| 97 | below. All the others are the only ones supported by the MS | ||
| 98 | runtime. */ | ||
| 99 | if (!(sig == SIGCHLD || sig == SIGSEGV || sig == SIGILL | ||
| 100 | || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM)) | ||
| 96 | { | 101 | { |
| 97 | errno = EINVAL; | 102 | errno = EINVAL; |
| 98 | return SIG_ERR; | 103 | return SIG_ERR; |
| 99 | } | 104 | } |
| 100 | old = sig_handlers[sig]; | 105 | old = sig_handlers[sig]; |
| 101 | sig_handlers[sig] = handler; | 106 | /* SIGABRT is treated specially because w32.c installs term_ntproc |
| 107 | as its handler, so we don't want to override that afterwards. | ||
| 108 | Aborting Emacs works specially anyway: either by calling | ||
| 109 | emacs_abort directly or through terminate_due_to_signal, which | ||
| 110 | calls emacs_abort through emacs_raise. */ | ||
| 111 | if (!(sig == SIGABRT && old == term_ntproc)) | ||
| 112 | { | ||
| 113 | sig_handlers[sig] = handler; | ||
| 114 | if (sig != SIGCHLD) | ||
| 115 | signal (sig, handler); | ||
| 116 | } | ||
| 102 | return old; | 117 | return old; |
| 103 | } | 118 | } |
| 104 | 119 | ||
| @@ -106,23 +121,26 @@ sys_signal (int sig, signal_handler handler) | |||
| 106 | int | 121 | int |
| 107 | sigaction (int sig, const struct sigaction *act, struct sigaction *oact) | 122 | sigaction (int sig, const struct sigaction *act, struct sigaction *oact) |
| 108 | { | 123 | { |
| 109 | signal_handler old; | 124 | signal_handler old = SIG_DFL; |
| 125 | int retval = 0; | ||
| 110 | 126 | ||
| 111 | if (sig != SIGCHLD) | 127 | if (act) |
| 128 | old = sys_signal (sig, act->sa_handler); | ||
| 129 | else if (oact) | ||
| 130 | old = sig_handlers[sig]; | ||
| 131 | |||
| 132 | if (old == SIG_ERR) | ||
| 112 | { | 133 | { |
| 113 | errno = EINVAL; | 134 | errno = EINVAL; |
| 114 | return -1; | 135 | retval = -1; |
| 115 | } | 136 | } |
| 116 | old = sig_handlers[sig]; | ||
| 117 | if (act) | ||
| 118 | sig_handlers[sig] = act->sa_handler; | ||
| 119 | if (oact) | 137 | if (oact) |
| 120 | { | 138 | { |
| 121 | oact->sa_handler = old; | 139 | oact->sa_handler = old; |
| 122 | oact->sa_flags = 0; | 140 | oact->sa_flags = 0; |
| 123 | oact->sa_mask = empty_mask; | 141 | oact->sa_mask = empty_mask; |
| 124 | } | 142 | } |
| 125 | return 0; | 143 | return retval; |
| 126 | } | 144 | } |
| 127 | 145 | ||
| 128 | /* Defined in <process.h> which conflicts with the local copy */ | 146 | /* Defined in <process.h> which conflicts with the local copy */ |
| @@ -1420,6 +1438,7 @@ find_child_console (HWND hwnd, LPARAM arg) | |||
| 1420 | return TRUE; | 1438 | return TRUE; |
| 1421 | } | 1439 | } |
| 1422 | 1440 | ||
| 1441 | /* Emulate 'kill', but only for other processes. */ | ||
| 1423 | int | 1442 | int |
| 1424 | sys_kill (int pid, int sig) | 1443 | sys_kill (int pid, int sig) |
| 1425 | { | 1444 | { |
| @@ -1428,9 +1447,6 @@ sys_kill (int pid, int sig) | |||
| 1428 | int need_to_free = 0; | 1447 | int need_to_free = 0; |
| 1429 | int rc = 0; | 1448 | int rc = 0; |
| 1430 | 1449 | ||
| 1431 | if (pid == getpid () && sig == SIGABRT) | ||
| 1432 | emacs_abort (); | ||
| 1433 | |||
| 1434 | /* Only handle signals that will result in the process dying */ | 1450 | /* Only handle signals that will result in the process dying */ |
| 1435 | if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | 1451 | if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) |
| 1436 | { | 1452 | { |
| @@ -1441,6 +1457,11 @@ sys_kill (int pid, int sig) | |||
| 1441 | cp = find_child_pid (pid); | 1457 | cp = find_child_pid (pid); |
| 1442 | if (cp == NULL) | 1458 | if (cp == NULL) |
| 1443 | { | 1459 | { |
| 1460 | /* We were passed a PID of something other than our subprocess. | ||
| 1461 | If that is our own PID, we will send to ourself a message to | ||
| 1462 | close the selected frame, which does not necessarily | ||
| 1463 | terminates Emacs. But then we are not supposed to call | ||
| 1464 | sys_kill with our own PID. */ | ||
| 1444 | proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); | 1465 | proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); |
| 1445 | if (proc_hand == NULL) | 1466 | if (proc_hand == NULL) |
| 1446 | { | 1467 | { |