diff options
Diffstat (limited to 'src/sysdep.c')
| -rw-r--r-- | src/sysdep.c | 413 |
1 files changed, 316 insertions, 97 deletions
diff --git a/src/sysdep.c b/src/sysdep.c index dbfd9efc7d4..dc7f6c2ad56 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -279,10 +279,6 @@ init_baud_rate (int fd) | |||
| 279 | 279 | ||
| 280 | 280 | ||
| 281 | 281 | ||
| 282 | /* Set nonzero to make following function work under dbx | ||
| 283 | (at least for bsd). */ | ||
| 284 | int wait_debugging EXTERNALLY_VISIBLE; | ||
| 285 | |||
| 286 | #ifndef MSDOS | 282 | #ifndef MSDOS |
| 287 | 283 | ||
| 288 | static void | 284 | static void |
| @@ -290,48 +286,24 @@ wait_for_termination_1 (pid_t pid, int interruptible) | |||
| 290 | { | 286 | { |
| 291 | while (1) | 287 | while (1) |
| 292 | { | 288 | { |
| 293 | #if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__) | ||
| 294 | /* Note that kill returns -1 even if the process is just a zombie now. | ||
| 295 | But inevitably a SIGCHLD interrupt should be generated | ||
| 296 | and child_sig will do waitpid and make the process go away. */ | ||
| 297 | /* There is some indication that there is a bug involved with | ||
| 298 | termination of subprocesses, perhaps involving a kernel bug too, | ||
| 299 | but no idea what it is. Just as a hunch we signal SIGCHLD to see | ||
| 300 | if that causes the problem to go away or get worse. */ | ||
| 301 | sigset_t sigchild_mask; | ||
| 302 | sigemptyset (&sigchild_mask); | ||
| 303 | sigaddset (&sigchild_mask, SIGCHLD); | ||
| 304 | pthread_sigmask (SIG_SETMASK, &sigchild_mask, 0); | ||
| 305 | |||
| 306 | if (0 > kill (pid, 0)) | ||
| 307 | { | ||
| 308 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); | ||
| 309 | kill (getpid (), SIGCHLD); | ||
| 310 | break; | ||
| 311 | } | ||
| 312 | if (wait_debugging) | ||
| 313 | sleep (1); | ||
| 314 | else | ||
| 315 | sigsuspend (&empty_mask); | ||
| 316 | #else /* not BSD_SYSTEM, and not HPUX version >= 6 */ | ||
| 317 | #ifdef WINDOWSNT | 289 | #ifdef WINDOWSNT |
| 318 | wait (0); | 290 | wait (0); |
| 319 | break; | 291 | break; |
| 320 | #else /* not WINDOWSNT */ | 292 | #else /* not WINDOWSNT */ |
| 321 | sigset_t blocked; | 293 | int status; |
| 322 | sigemptyset (&blocked); | 294 | int wait_result = waitpid (pid, &status, 0); |
| 323 | sigaddset (&blocked, SIGCHLD); | 295 | if (wait_result < 0) |
| 324 | pthread_sigmask (SIG_BLOCK, &blocked, 0); | ||
| 325 | errno = 0; | ||
| 326 | if (kill (pid, 0) == -1 && errno == ESRCH) | ||
| 327 | { | 296 | { |
| 328 | pthread_sigmask (SIG_UNBLOCK, &blocked, 0); | 297 | if (errno != EINTR) |
| 298 | break; | ||
| 299 | } | ||
| 300 | else | ||
| 301 | { | ||
| 302 | record_child_status_change (wait_result, status); | ||
| 329 | break; | 303 | break; |
| 330 | } | 304 | } |
| 331 | 305 | ||
| 332 | sigsuspend (&empty_mask); | ||
| 333 | #endif /* not WINDOWSNT */ | 306 | #endif /* not WINDOWSNT */ |
| 334 | #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */ | ||
| 335 | if (interruptible) | 307 | if (interruptible) |
| 336 | QUIT; | 308 | QUIT; |
| 337 | } | 309 | } |
| @@ -1438,40 +1410,77 @@ init_system_name (void) | |||
| 1438 | 1410 | ||
| 1439 | sigset_t empty_mask; | 1411 | sigset_t empty_mask; |
| 1440 | 1412 | ||
| 1441 | /* Store into *ACTION a signal action suitable for Emacs, with handler | 1413 | static struct sigaction process_fatal_action; |
| 1442 | HANDLER. */ | 1414 | |
| 1443 | void | 1415 | static int |
| 1444 | emacs_sigaction_init (struct sigaction *action, signal_handler_t handler) | 1416 | emacs_sigaction_flags (void) |
| 1445 | { | 1417 | { |
| 1446 | sigemptyset (&action->sa_mask); | 1418 | #ifdef SA_RESTART |
| 1447 | action->sa_handler = handler; | ||
| 1448 | action->sa_flags = 0; | ||
| 1449 | #if defined (SA_RESTART) | ||
| 1450 | /* SA_RESTART causes interruptible functions with timeouts (e.g., | 1419 | /* SA_RESTART causes interruptible functions with timeouts (e.g., |
| 1451 | 'select') to reset their timeout on some platforms (e.g., | 1420 | 'select') to reset their timeout on some platforms (e.g., |
| 1452 | HP-UX 11), which is not what we want. Also, when Emacs is | 1421 | HP-UX 11), which is not what we want. Also, when Emacs is |
| 1453 | interactive, we don't want SA_RESTART because we need to poll | 1422 | interactive, we don't want SA_RESTART because we need to poll |
| 1454 | for pending input so we need long-running syscalls to be interrupted | 1423 | for pending input so we need long-running syscalls to be interrupted |
| 1455 | after a signal that sets the interrupt_input_pending flag. */ | 1424 | after a signal that sets pending_signals. |
| 1456 | /* Non-interactive keyboard input goes through stdio, where we always | 1425 | |
| 1457 | want restartable system calls. */ | 1426 | Non-interactive keyboard input goes through stdio, where we |
| 1427 | always want restartable system calls. */ | ||
| 1458 | if (noninteractive) | 1428 | if (noninteractive) |
| 1459 | action->sa_flags = SA_RESTART; | 1429 | return SA_RESTART; |
| 1460 | #endif | 1430 | #endif |
| 1431 | return 0; | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | /* Store into *ACTION a signal action suitable for Emacs, with handler | ||
| 1435 | HANDLER. */ | ||
| 1436 | void | ||
| 1437 | emacs_sigaction_init (struct sigaction *action, signal_handler_t handler) | ||
| 1438 | { | ||
| 1439 | sigemptyset (&action->sa_mask); | ||
| 1440 | |||
| 1441 | /* When handling a signal, block nonfatal system signals that are caught | ||
| 1442 | by Emacs. This makes race conditions less likely. */ | ||
| 1443 | sigaddset (&action->sa_mask, SIGALRM); | ||
| 1444 | #ifdef SIGCHLD | ||
| 1445 | sigaddset (&action->sa_mask, SIGCHLD); | ||
| 1446 | #endif | ||
| 1447 | #ifdef SIGDANGER | ||
| 1448 | sigaddset (&action->sa_mask, SIGDANGER); | ||
| 1449 | #endif | ||
| 1450 | #ifdef SIGWINCH | ||
| 1451 | sigaddset (&action->sa_mask, SIGWINCH); | ||
| 1452 | #endif | ||
| 1453 | if (! noninteractive) | ||
| 1454 | { | ||
| 1455 | sigaddset (&action->sa_mask, SIGINT); | ||
| 1456 | sigaddset (&action->sa_mask, SIGQUIT); | ||
| 1457 | #ifdef USABLE_SIGIO | ||
| 1458 | sigaddset (&action->sa_mask, SIGIO); | ||
| 1459 | #endif | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | if (! IEEE_FLOATING_POINT) | ||
| 1463 | sigaddset (&action->sa_mask, SIGFPE); | ||
| 1464 | |||
| 1465 | action->sa_handler = handler; | ||
| 1466 | action->sa_flags = emacs_sigaction_flags (); | ||
| 1461 | } | 1467 | } |
| 1462 | 1468 | ||
| 1463 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | 1469 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD |
| 1464 | static pthread_t main_thread; | 1470 | static pthread_t main_thread; |
| 1465 | #endif | 1471 | #endif |
| 1466 | 1472 | ||
| 1467 | /* If we are on the main thread, handle the signal SIG with HANDLER. | 1473 | /* SIG has arrived at the current process. Deliver it to the main |
| 1474 | thread, which should handle it with HANDLER. | ||
| 1475 | |||
| 1476 | If we are on the main thread, handle the signal SIG with HANDLER. | ||
| 1468 | Otherwise, redirect the signal to the main thread, blocking it from | 1477 | Otherwise, redirect the signal to the main thread, blocking it from |
| 1469 | this thread. POSIX says any thread can receive a signal that is | 1478 | this thread. POSIX says any thread can receive a signal that is |
| 1470 | associated with a process, process group, or asynchronous event. | 1479 | associated with a process, process group, or asynchronous event. |
| 1471 | On GNU/Linux that is not true, but for other systems (FreeBSD at | 1480 | On GNU/Linux that is not true, but for other systems (FreeBSD at |
| 1472 | least) it is. */ | 1481 | least) it is. */ |
| 1473 | void | 1482 | void |
| 1474 | handle_on_main_thread (int sig, signal_handler_t handler) | 1483 | deliver_process_signal (int sig, signal_handler_t handler) |
| 1475 | { | 1484 | { |
| 1476 | /* Preserve errno, to avoid race conditions with signal handlers that | 1485 | /* Preserve errno, to avoid race conditions with signal handlers that |
| 1477 | might change errno. Races can occur even in single-threaded hosts. */ | 1486 | might change errno. Races can occur even in single-threaded hosts. */ |
| @@ -1494,6 +1503,39 @@ handle_on_main_thread (int sig, signal_handler_t handler) | |||
| 1494 | 1503 | ||
| 1495 | errno = old_errno; | 1504 | errno = old_errno; |
| 1496 | } | 1505 | } |
| 1506 | |||
| 1507 | /* Static location to save a fatal backtrace in a thread. | ||
| 1508 | FIXME: If two subsidiary threads fail simultaneously, the resulting | ||
| 1509 | backtrace may be garbage. */ | ||
| 1510 | enum { BACKTRACE_LIMIT_MAX = 500 }; | ||
| 1511 | static void *thread_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1]; | ||
| 1512 | static int thread_backtrace_npointers; | ||
| 1513 | |||
| 1514 | /* SIG has arrived at the current thread. | ||
| 1515 | If we are on the main thread, handle the signal SIG with HANDLER. | ||
| 1516 | Otherwise, this is a fatal error in the handling thread. */ | ||
| 1517 | static void | ||
| 1518 | deliver_thread_signal (int sig, signal_handler_t handler) | ||
| 1519 | { | ||
| 1520 | int old_errno = errno; | ||
| 1521 | |||
| 1522 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 1523 | if (! pthread_equal (pthread_self (), main_thread)) | ||
| 1524 | { | ||
| 1525 | thread_backtrace_npointers | ||
| 1526 | = backtrace (thread_backtrace_buffer, BACKTRACE_LIMIT_MAX); | ||
| 1527 | sigaction (sig, &process_fatal_action, 0); | ||
| 1528 | pthread_kill (main_thread, sig); | ||
| 1529 | |||
| 1530 | /* Avoid further damage while the main thread is exiting. */ | ||
| 1531 | while (1) | ||
| 1532 | sigsuspend (&empty_mask); | ||
| 1533 | } | ||
| 1534 | #endif | ||
| 1535 | |||
| 1536 | handler (sig); | ||
| 1537 | errno = old_errno; | ||
| 1538 | } | ||
| 1497 | 1539 | ||
| 1498 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST | 1540 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST |
| 1499 | static char *my_sys_siglist[NSIG]; | 1541 | static char *my_sys_siglist[NSIG]; |
| @@ -1503,9 +1545,60 @@ static char *my_sys_siglist[NSIG]; | |||
| 1503 | # define sys_siglist my_sys_siglist | 1545 | # define sys_siglist my_sys_siglist |
| 1504 | #endif | 1546 | #endif |
| 1505 | 1547 | ||
| 1548 | /* Handle bus errors, invalid instruction, etc. */ | ||
| 1549 | static void | ||
| 1550 | handle_fatal_signal (int sig) | ||
| 1551 | { | ||
| 1552 | terminate_due_to_signal (sig, 10); | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | static void | ||
| 1556 | deliver_fatal_signal (int sig) | ||
| 1557 | { | ||
| 1558 | deliver_process_signal (sig, handle_fatal_signal); | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | static void | ||
| 1562 | deliver_fatal_thread_signal (int sig) | ||
| 1563 | { | ||
| 1564 | deliver_thread_signal (sig, handle_fatal_signal); | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | static _Noreturn void | ||
| 1568 | handle_arith_signal (int sig) | ||
| 1569 | { | ||
| 1570 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); | ||
| 1571 | xsignal0 (Qarith_error); | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | static void | ||
| 1575 | deliver_arith_signal (int sig) | ||
| 1576 | { | ||
| 1577 | deliver_thread_signal (sig, handle_arith_signal); | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | /* Treat SIG as a terminating signal, unless it is already ignored and | ||
| 1581 | we are in --batch mode. Among other things, this makes nohup work. */ | ||
| 1582 | static void | ||
| 1583 | maybe_fatal_sig (int sig) | ||
| 1584 | { | ||
| 1585 | bool catch_sig = !noninteractive; | ||
| 1586 | if (!catch_sig) | ||
| 1587 | { | ||
| 1588 | struct sigaction old_action; | ||
| 1589 | sigaction (sig, 0, &old_action); | ||
| 1590 | catch_sig = old_action.sa_handler != SIG_IGN; | ||
| 1591 | } | ||
| 1592 | if (catch_sig) | ||
| 1593 | sigaction (sig, &process_fatal_action, 0); | ||
| 1594 | } | ||
| 1595 | |||
| 1506 | void | 1596 | void |
| 1507 | init_signals (void) | 1597 | init_signals (bool dumping) |
| 1508 | { | 1598 | { |
| 1599 | struct sigaction thread_fatal_action; | ||
| 1600 | struct sigaction action; | ||
| 1601 | |||
| 1509 | sigemptyset (&empty_mask); | 1602 | sigemptyset (&empty_mask); |
| 1510 | 1603 | ||
| 1511 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | 1604 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD |
| @@ -1515,9 +1608,7 @@ init_signals (void) | |||
| 1515 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST | 1608 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST |
| 1516 | if (! initialized) | 1609 | if (! initialized) |
| 1517 | { | 1610 | { |
| 1518 | # ifdef SIGABRT | ||
| 1519 | sys_siglist[SIGABRT] = "Aborted"; | 1611 | sys_siglist[SIGABRT] = "Aborted"; |
| 1520 | # endif | ||
| 1521 | # ifdef SIGAIO | 1612 | # ifdef SIGAIO |
| 1522 | sys_siglist[SIGAIO] = "LAN I/O interrupt"; | 1613 | sys_siglist[SIGAIO] = "LAN I/O interrupt"; |
| 1523 | # endif | 1614 | # endif |
| @@ -1545,9 +1636,7 @@ init_signals (void) | |||
| 1545 | # ifdef SIGEMT | 1636 | # ifdef SIGEMT |
| 1546 | sys_siglist[SIGEMT] = "Emulation trap"; | 1637 | sys_siglist[SIGEMT] = "Emulation trap"; |
| 1547 | # endif | 1638 | # endif |
| 1548 | # ifdef SIGFPE | ||
| 1549 | sys_siglist[SIGFPE] = "Arithmetic exception"; | 1639 | sys_siglist[SIGFPE] = "Arithmetic exception"; |
| 1550 | # endif | ||
| 1551 | # ifdef SIGFREEZE | 1640 | # ifdef SIGFREEZE |
| 1552 | sys_siglist[SIGFREEZE] = "SIGFREEZE"; | 1641 | sys_siglist[SIGFREEZE] = "SIGFREEZE"; |
| 1553 | # endif | 1642 | # endif |
| @@ -1557,12 +1646,8 @@ init_signals (void) | |||
| 1557 | # ifdef SIGHUP | 1646 | # ifdef SIGHUP |
| 1558 | sys_siglist[SIGHUP] = "Hangup"; | 1647 | sys_siglist[SIGHUP] = "Hangup"; |
| 1559 | # endif | 1648 | # endif |
| 1560 | # ifdef SIGILL | ||
| 1561 | sys_siglist[SIGILL] = "Illegal instruction"; | 1649 | sys_siglist[SIGILL] = "Illegal instruction"; |
| 1562 | # endif | ||
| 1563 | # ifdef SIGINT | ||
| 1564 | sys_siglist[SIGINT] = "Interrupt"; | 1650 | sys_siglist[SIGINT] = "Interrupt"; |
| 1565 | # endif | ||
| 1566 | # ifdef SIGIO | 1651 | # ifdef SIGIO |
| 1567 | sys_siglist[SIGIO] = "I/O possible"; | 1652 | sys_siglist[SIGIO] = "I/O possible"; |
| 1568 | # endif | 1653 | # endif |
| @@ -1611,9 +1696,7 @@ init_signals (void) | |||
| 1611 | # ifdef SIGSAK | 1696 | # ifdef SIGSAK |
| 1612 | sys_siglist[SIGSAK] = "Secure attention"; | 1697 | sys_siglist[SIGSAK] = "Secure attention"; |
| 1613 | # endif | 1698 | # endif |
| 1614 | # ifdef SIGSEGV | ||
| 1615 | sys_siglist[SIGSEGV] = "Segmentation violation"; | 1699 | sys_siglist[SIGSEGV] = "Segmentation violation"; |
| 1616 | # endif | ||
| 1617 | # ifdef SIGSOUND | 1700 | # ifdef SIGSOUND |
| 1618 | sys_siglist[SIGSOUND] = "Sound completed"; | 1701 | sys_siglist[SIGSOUND] = "Sound completed"; |
| 1619 | # endif | 1702 | # endif |
| @@ -1626,9 +1709,7 @@ init_signals (void) | |||
| 1626 | # ifdef SIGSYS | 1709 | # ifdef SIGSYS |
| 1627 | sys_siglist[SIGSYS] = "Bad argument to system call"; | 1710 | sys_siglist[SIGSYS] = "Bad argument to system call"; |
| 1628 | # endif | 1711 | # endif |
| 1629 | # ifdef SIGTERM | ||
| 1630 | sys_siglist[SIGTERM] = "Terminated"; | 1712 | sys_siglist[SIGTERM] = "Terminated"; |
| 1631 | # endif | ||
| 1632 | # ifdef SIGTHAW | 1713 | # ifdef SIGTHAW |
| 1633 | sys_siglist[SIGTHAW] = "SIGTHAW"; | 1714 | sys_siglist[SIGTHAW] = "SIGTHAW"; |
| 1634 | # endif | 1715 | # endif |
| @@ -1673,6 +1754,129 @@ init_signals (void) | |||
| 1673 | # endif | 1754 | # endif |
| 1674 | } | 1755 | } |
| 1675 | #endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */ | 1756 | #endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */ |
| 1757 | |||
| 1758 | /* Don't alter signal handlers if dumping. On some machines, | ||
| 1759 | changing signal handlers sets static data that would make signals | ||
| 1760 | fail to work right when the dumped Emacs is run. */ | ||
| 1761 | if (dumping) | ||
| 1762 | return; | ||
| 1763 | |||
| 1764 | sigfillset (&process_fatal_action.sa_mask); | ||
| 1765 | process_fatal_action.sa_handler = deliver_fatal_signal; | ||
| 1766 | process_fatal_action.sa_flags = emacs_sigaction_flags () | SA_NODEFER; | ||
| 1767 | |||
| 1768 | sigfillset (&thread_fatal_action.sa_mask); | ||
| 1769 | thread_fatal_action.sa_handler = deliver_fatal_thread_signal; | ||
| 1770 | thread_fatal_action.sa_flags = process_fatal_action.sa_flags; | ||
| 1771 | |||
| 1772 | /* SIGINT may need special treatment on MS-Windows. See | ||
| 1773 | http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html | ||
| 1774 | Please update the doc of kill-emacs, kill-emacs-hook, and | ||
| 1775 | NEWS if you change this. */ | ||
| 1776 | |||
| 1777 | maybe_fatal_sig (SIGHUP); | ||
| 1778 | maybe_fatal_sig (SIGINT); | ||
| 1779 | maybe_fatal_sig (SIGTERM); | ||
| 1780 | |||
| 1781 | /* Emacs checks for write errors, so it can safely ignore SIGPIPE. | ||
| 1782 | However, in batch mode leave SIGPIPE alone, as that causes Emacs | ||
| 1783 | to behave more like typical batch applications do. */ | ||
| 1784 | if (! noninteractive) | ||
| 1785 | signal (SIGPIPE, SIG_IGN); | ||
| 1786 | |||
| 1787 | sigaction (SIGQUIT, &process_fatal_action, 0); | ||
| 1788 | sigaction (SIGILL, &thread_fatal_action, 0); | ||
| 1789 | sigaction (SIGTRAP, &thread_fatal_action, 0); | ||
| 1790 | |||
| 1791 | /* Typically SIGFPE is thread-specific and is fatal, like SIGILL. | ||
| 1792 | But on a non-IEEE host SIGFPE can come from a trap in the Lisp | ||
| 1793 | interpreter's floating point operations, so treat SIGFPE as an | ||
| 1794 | arith-error if it arises in the main thread. */ | ||
| 1795 | if (IEEE_FLOATING_POINT) | ||
| 1796 | sigaction (SIGFPE, &thread_fatal_action, 0); | ||
| 1797 | else | ||
| 1798 | { | ||
| 1799 | emacs_sigaction_init (&action, deliver_arith_signal); | ||
| 1800 | sigaction (SIGFPE, &action, 0); | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | #ifdef SIGUSR1 | ||
| 1804 | add_user_signal (SIGUSR1, "sigusr1"); | ||
| 1805 | #endif | ||
| 1806 | #ifdef SIGUSR2 | ||
| 1807 | add_user_signal (SIGUSR2, "sigusr2"); | ||
| 1808 | #endif | ||
| 1809 | sigaction (SIGABRT, &thread_fatal_action, 0); | ||
| 1810 | #ifdef SIGPRE | ||
| 1811 | sigaction (SIGPRE, &thread_fatal_action, 0); | ||
| 1812 | #endif | ||
| 1813 | #ifdef SIGORE | ||
| 1814 | sigaction (SIGORE, &thread_fatal_action, 0); | ||
| 1815 | #endif | ||
| 1816 | #ifdef SIGUME | ||
| 1817 | sigaction (SIGUME, &thread_fatal_action, 0); | ||
| 1818 | #endif | ||
| 1819 | #ifdef SIGDLK | ||
| 1820 | sigaction (SIGDLK, &process_fatal_action, 0); | ||
| 1821 | #endif | ||
| 1822 | #ifdef SIGCPULIM | ||
| 1823 | sigaction (SIGCPULIM, &process_fatal_action, 0); | ||
| 1824 | #endif | ||
| 1825 | #ifdef SIGIOT | ||
| 1826 | sigaction (SIGIOT, &thread_fatal_action, 0); | ||
| 1827 | #endif | ||
| 1828 | #ifdef SIGEMT | ||
| 1829 | sigaction (SIGEMT, &thread_fatal_action, 0); | ||
| 1830 | #endif | ||
| 1831 | #ifdef SIGBUS | ||
| 1832 | sigaction (SIGBUS, &thread_fatal_action, 0); | ||
| 1833 | #endif | ||
| 1834 | sigaction (SIGSEGV, &thread_fatal_action, 0); | ||
| 1835 | #ifdef SIGSYS | ||
| 1836 | sigaction (SIGSYS, &thread_fatal_action, 0); | ||
| 1837 | #endif | ||
| 1838 | sigaction (SIGTERM, &process_fatal_action, 0); | ||
| 1839 | #ifdef SIGPROF | ||
| 1840 | sigaction (SIGPROF, &process_fatal_action, 0); | ||
| 1841 | #endif | ||
| 1842 | #ifdef SIGVTALRM | ||
| 1843 | sigaction (SIGVTALRM, &process_fatal_action, 0); | ||
| 1844 | #endif | ||
| 1845 | #ifdef SIGXCPU | ||
| 1846 | sigaction (SIGXCPU, &process_fatal_action, 0); | ||
| 1847 | #endif | ||
| 1848 | #ifdef SIGXFSZ | ||
| 1849 | sigaction (SIGXFSZ, &process_fatal_action, 0); | ||
| 1850 | #endif | ||
| 1851 | |||
| 1852 | #ifdef SIGDANGER | ||
| 1853 | /* This just means available memory is getting low. */ | ||
| 1854 | emacs_sigaction_init (&action, deliver_danger_signal); | ||
| 1855 | sigaction (SIGDANGER, &action, 0); | ||
| 1856 | #endif | ||
| 1857 | |||
| 1858 | /* AIX-specific signals. */ | ||
| 1859 | #ifdef SIGGRANT | ||
| 1860 | sigaction (SIGGRANT, &process_fatal_action, 0); | ||
| 1861 | #endif | ||
| 1862 | #ifdef SIGMIGRATE | ||
| 1863 | sigaction (SIGMIGRATE, &process_fatal_action, 0); | ||
| 1864 | #endif | ||
| 1865 | #ifdef SIGMSG | ||
| 1866 | sigaction (SIGMSG, &process_fatal_action, 0); | ||
| 1867 | #endif | ||
| 1868 | #ifdef SIGRETRACT | ||
| 1869 | sigaction (SIGRETRACT, &process_fatal_action, 0); | ||
| 1870 | #endif | ||
| 1871 | #ifdef SIGSAK | ||
| 1872 | sigaction (SIGSAK, &process_fatal_action, 0); | ||
| 1873 | #endif | ||
| 1874 | #ifdef SIGSOUND | ||
| 1875 | sigaction (SIGSOUND, &process_fatal_action, 0); | ||
| 1876 | #endif | ||
| 1877 | #ifdef SIGTALRM | ||
| 1878 | sigaction (SIGTALRM, &thread_fatal_action, 0); | ||
| 1879 | #endif | ||
| 1676 | } | 1880 | } |
| 1677 | 1881 | ||
| 1678 | #ifndef HAVE_RANDOM | 1882 | #ifndef HAVE_RANDOM |
| @@ -1811,23 +2015,37 @@ snprintf (char *buf, size_t bufsize, char const *format, ...) | |||
| 1811 | void | 2015 | void |
| 1812 | emacs_backtrace (int backtrace_limit) | 2016 | emacs_backtrace (int backtrace_limit) |
| 1813 | { | 2017 | { |
| 1814 | enum { BACKTRACE_LIMIT_MAX = 500 }; | 2018 | void *main_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1]; |
| 1815 | void *buffer[BACKTRACE_LIMIT_MAX + 1]; | ||
| 1816 | int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX); | 2019 | int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX); |
| 1817 | int npointers = backtrace (buffer, bounded_limit + 1); | 2020 | void *buffer; |
| 2021 | int npointers; | ||
| 2022 | |||
| 2023 | if (thread_backtrace_npointers) | ||
| 2024 | { | ||
| 2025 | buffer = thread_backtrace_buffer; | ||
| 2026 | npointers = thread_backtrace_npointers; | ||
| 2027 | } | ||
| 2028 | else | ||
| 2029 | { | ||
| 2030 | buffer = main_backtrace_buffer; | ||
| 2031 | npointers = backtrace (buffer, bounded_limit + 1); | ||
| 2032 | } | ||
| 2033 | |||
| 1818 | if (npointers) | 2034 | if (npointers) |
| 1819 | ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); | 2035 | { |
| 1820 | backtrace_symbols_fd (buffer, bounded_limit, STDERR_FILENO); | 2036 | ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); |
| 1821 | if (bounded_limit < npointers) | 2037 | backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); |
| 1822 | ignore_value (write (STDERR_FILENO, "...\n", 4)); | 2038 | if (bounded_limit < npointers) |
| 2039 | ignore_value (write (STDERR_FILENO, "...\n", 4)); | ||
| 2040 | } | ||
| 1823 | } | 2041 | } |
| 1824 | 2042 | ||
| 1825 | #ifndef HAVE_NTGUI | 2043 | #ifndef HAVE_NTGUI |
| 1826 | /* Using emacs_abort lets GDB return from a breakpoint here. */ | ||
| 1827 | void | 2044 | void |
| 1828 | emacs_abort (void) | 2045 | emacs_abort (void) |
| 1829 | { | 2046 | { |
| 1830 | fatal_error_backtrace (SIGABRT, 10); | 2047 | signal (SIGABRT, SIG_DFL); |
| 2048 | terminate_due_to_signal (SIGABRT, 10); | ||
| 1831 | } | 2049 | } |
| 1832 | #endif | 2050 | #endif |
| 1833 | 2051 | ||
| @@ -1910,7 +2128,8 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) | |||
| 1910 | { | 2128 | { |
| 1911 | /* I originally used `QUIT' but that might causes files to | 2129 | /* I originally used `QUIT' but that might causes files to |
| 1912 | be truncated if you hit C-g in the middle of it. --Stef */ | 2130 | be truncated if you hit C-g in the middle of it. --Stef */ |
| 1913 | process_pending_signals (); | 2131 | if (pending_signals) |
| 2132 | process_pending_signals (); | ||
| 1914 | continue; | 2133 | continue; |
| 1915 | } | 2134 | } |
| 1916 | else | 2135 | else |
| @@ -1975,11 +2194,11 @@ getwd (char *pathname) | |||
| 1975 | char *npath, *spath; | 2194 | char *npath, *spath; |
| 1976 | extern char *getcwd (char *, size_t); | 2195 | extern char *getcwd (char *, size_t); |
| 1977 | 2196 | ||
| 1978 | BLOCK_INPUT; /* getcwd uses malloc */ | 2197 | block_input (); /* getcwd uses malloc */ |
| 1979 | spath = npath = getcwd ((char *) 0, MAXPATHLEN); | 2198 | spath = npath = getcwd ((char *) 0, MAXPATHLEN); |
| 1980 | if (spath == 0) | 2199 | if (spath == 0) |
| 1981 | { | 2200 | { |
| 1982 | UNBLOCK_INPUT; | 2201 | unblock_input (); |
| 1983 | return spath; | 2202 | return spath; |
| 1984 | } | 2203 | } |
| 1985 | /* On Altos 3068, getcwd can return @hostname/dir, so discard | 2204 | /* On Altos 3068, getcwd can return @hostname/dir, so discard |
| @@ -1988,7 +2207,7 @@ getwd (char *pathname) | |||
| 1988 | npath++; | 2207 | npath++; |
| 1989 | strcpy (pathname, npath); | 2208 | strcpy (pathname, npath); |
| 1990 | free (spath); /* getcwd uses malloc */ | 2209 | free (spath); /* getcwd uses malloc */ |
| 1991 | UNBLOCK_INPUT; | 2210 | unblock_input (); |
| 1992 | return pathname; | 2211 | return pathname; |
| 1993 | } | 2212 | } |
| 1994 | 2213 | ||
| @@ -2422,7 +2641,7 @@ get_up_time (void) | |||
| 2422 | FILE *fup; | 2641 | FILE *fup; |
| 2423 | EMACS_TIME up = make_emacs_time (0, 0); | 2642 | EMACS_TIME up = make_emacs_time (0, 0); |
| 2424 | 2643 | ||
| 2425 | BLOCK_INPUT; | 2644 | block_input (); |
| 2426 | fup = fopen ("/proc/uptime", "r"); | 2645 | fup = fopen ("/proc/uptime", "r"); |
| 2427 | 2646 | ||
| 2428 | if (fup) | 2647 | if (fup) |
| @@ -2453,7 +2672,7 @@ get_up_time (void) | |||
| 2453 | } | 2672 | } |
| 2454 | fclose (fup); | 2673 | fclose (fup); |
| 2455 | } | 2674 | } |
| 2456 | UNBLOCK_INPUT; | 2675 | unblock_input (); |
| 2457 | 2676 | ||
| 2458 | return up; | 2677 | return up; |
| 2459 | } | 2678 | } |
| @@ -2467,7 +2686,7 @@ procfs_ttyname (int rdev) | |||
| 2467 | FILE *fdev = NULL; | 2686 | FILE *fdev = NULL; |
| 2468 | char name[PATH_MAX]; | 2687 | char name[PATH_MAX]; |
| 2469 | 2688 | ||
| 2470 | BLOCK_INPUT; | 2689 | block_input (); |
| 2471 | fdev = fopen ("/proc/tty/drivers", "r"); | 2690 | fdev = fopen ("/proc/tty/drivers", "r"); |
| 2472 | 2691 | ||
| 2473 | if (fdev) | 2692 | if (fdev) |
| @@ -2499,7 +2718,7 @@ procfs_ttyname (int rdev) | |||
| 2499 | } | 2718 | } |
| 2500 | fclose (fdev); | 2719 | fclose (fdev); |
| 2501 | } | 2720 | } |
| 2502 | UNBLOCK_INPUT; | 2721 | unblock_input (); |
| 2503 | return build_string (name); | 2722 | return build_string (name); |
| 2504 | } | 2723 | } |
| 2505 | 2724 | ||
| @@ -2509,7 +2728,7 @@ procfs_get_total_memory (void) | |||
| 2509 | FILE *fmem = NULL; | 2728 | FILE *fmem = NULL; |
| 2510 | unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ | 2729 | unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ |
| 2511 | 2730 | ||
| 2512 | BLOCK_INPUT; | 2731 | block_input (); |
| 2513 | fmem = fopen ("/proc/meminfo", "r"); | 2732 | fmem = fopen ("/proc/meminfo", "r"); |
| 2514 | 2733 | ||
| 2515 | if (fmem) | 2734 | if (fmem) |
| @@ -2528,7 +2747,7 @@ procfs_get_total_memory (void) | |||
| 2528 | } | 2747 | } |
| 2529 | fclose (fmem); | 2748 | fclose (fmem); |
| 2530 | } | 2749 | } |
| 2531 | UNBLOCK_INPUT; | 2750 | unblock_input (); |
| 2532 | return retval; | 2751 | return retval; |
| 2533 | } | 2752 | } |
| 2534 | 2753 | ||
| @@ -2574,17 +2793,17 @@ system_process_attributes (Lisp_Object pid) | |||
| 2574 | /* euid egid */ | 2793 | /* euid egid */ |
| 2575 | uid = st.st_uid; | 2794 | uid = st.st_uid; |
| 2576 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); | 2795 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); |
| 2577 | BLOCK_INPUT; | 2796 | block_input (); |
| 2578 | pw = getpwuid (uid); | 2797 | pw = getpwuid (uid); |
| 2579 | UNBLOCK_INPUT; | 2798 | unblock_input (); |
| 2580 | if (pw) | 2799 | if (pw) |
| 2581 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); | 2800 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); |
| 2582 | 2801 | ||
| 2583 | gid = st.st_gid; | 2802 | gid = st.st_gid; |
| 2584 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs); | 2803 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs); |
| 2585 | BLOCK_INPUT; | 2804 | block_input (); |
| 2586 | gr = getgrgid (gid); | 2805 | gr = getgrgid (gid); |
| 2587 | UNBLOCK_INPUT; | 2806 | unblock_input (); |
| 2588 | if (gr) | 2807 | if (gr) |
| 2589 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); | 2808 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); |
| 2590 | 2809 | ||
| @@ -2812,17 +3031,17 @@ system_process_attributes (Lisp_Object pid) | |||
| 2812 | /* euid egid */ | 3031 | /* euid egid */ |
| 2813 | uid = st.st_uid; | 3032 | uid = st.st_uid; |
| 2814 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); | 3033 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); |
| 2815 | BLOCK_INPUT; | 3034 | block_input (); |
| 2816 | pw = getpwuid (uid); | 3035 | pw = getpwuid (uid); |
| 2817 | UNBLOCK_INPUT; | 3036 | unblock_input (); |
| 2818 | if (pw) | 3037 | if (pw) |
| 2819 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); | 3038 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); |
| 2820 | 3039 | ||
| 2821 | gid = st.st_gid; | 3040 | gid = st.st_gid; |
| 2822 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs); | 3041 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs); |
| 2823 | BLOCK_INPUT; | 3042 | block_input (); |
| 2824 | gr = getgrgid (gid); | 3043 | gr = getgrgid (gid); |
| 2825 | UNBLOCK_INPUT; | 3044 | unblock_input (); |
| 2826 | if (gr) | 3045 | if (gr) |
| 2827 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); | 3046 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); |
| 2828 | 3047 | ||
| @@ -2943,17 +3162,17 @@ system_process_attributes (Lisp_Object pid) | |||
| 2943 | 3162 | ||
| 2944 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs); | 3163 | attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs); |
| 2945 | 3164 | ||
| 2946 | BLOCK_INPUT; | 3165 | block_input (); |
| 2947 | pw = getpwuid (proc.ki_uid); | 3166 | pw = getpwuid (proc.ki_uid); |
| 2948 | UNBLOCK_INPUT; | 3167 | unblock_input (); |
| 2949 | if (pw) | 3168 | if (pw) |
| 2950 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); | 3169 | attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); |
| 2951 | 3170 | ||
| 2952 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs); | 3171 | attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs); |
| 2953 | 3172 | ||
| 2954 | BLOCK_INPUT; | 3173 | block_input (); |
| 2955 | gr = getgrgid (proc.ki_svgid); | 3174 | gr = getgrgid (proc.ki_svgid); |
| 2956 | UNBLOCK_INPUT; | 3175 | unblock_input (); |
| 2957 | if (gr) | 3176 | if (gr) |
| 2958 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); | 3177 | attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); |
| 2959 | 3178 | ||
| @@ -2993,9 +3212,9 @@ system_process_attributes (Lisp_Object pid) | |||
| 2993 | attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs); | 3212 | attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs); |
| 2994 | attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)), attrs); | 3213 | attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)), attrs); |
| 2995 | 3214 | ||
| 2996 | BLOCK_INPUT; | 3215 | block_input (); |
| 2997 | ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR); | 3216 | ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR); |
| 2998 | UNBLOCK_INPUT; | 3217 | unblock_input (); |
| 2999 | if (ttyname) | 3218 | if (ttyname) |
| 3000 | attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs); | 3219 | attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs); |
| 3001 | 3220 | ||