signal.c


DEFINITIONS

This source file includes following functions.
  1. signm2signo
  2. signo2signm
  3. rb_f_kill
  4. rb_gc_mark_trap_list
  5. RETSIGTYPE
  6. posix_signal
  7. signal_exec
  8. sighandler
  9. sigbus
  10. sigsegv
  11. sigpipe
  12. rb_trap_exit
  13. rb_trap_exec
  14. sigexit
  15. trap
  16. trap_ensure
  17. rb_trap_restore_mask
  18. sig_trap
  19. sig_list
  20. install_sighandler
  21. Init_signal


   1  /**********************************************************************
   2  
   3    signal.c -
   4  
   5    $Author: michal $
   6    $Date: 2002/08/28 14:59:01 $
   7    created at: Tue Dec 20 10:13:44 JST 1994
   8  
   9    Copyright (C) 1993-2002 Yukihiro Matsumoto
  10    Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
  11    Copyright (C) 2000  Information-technology Promotion Agency, Japan
  12  
  13  **********************************************************************/
  14  
  15  #include "ruby.h"
  16  #include "rubysig.h"
  17  #include <signal.h>
  18  #include <stdio.h>
  19  
  20  #ifdef __BEOS__
  21  #undef SIGBUS
  22  #endif
  23  
  24  #ifndef NSIG
  25  # ifdef DJGPP
  26  #  define NSIG SIGMAX
  27  # else
  28  #  define NSIG (_SIGMAX + 1)      /* For QNX */
  29  # endif
  30  #endif
  31  
  32  static struct signals {
  33      char *signm;
  34      int  signo;
  35  } siglist [] = {
  36  #ifdef SIGHUP
  37      {"HUP", SIGHUP},
  38  #endif
  39      {"INT", SIGINT},
  40  #ifdef SIGQUIT
  41      {"QUIT", SIGQUIT},
  42  #endif
  43  #ifdef SIGILL
  44      {"ILL", SIGILL},
  45  #endif
  46  #ifdef SIGTRAP
  47      {"TRAP", SIGTRAP},
  48  #endif
  49  #ifdef SIGIOT
  50      {"IOT", SIGIOT},
  51  #endif
  52  #ifdef SIGABRT
  53      {"ABRT", SIGABRT},
  54  #endif
  55  #ifdef SIGEMT
  56      {"EMT", SIGEMT},
  57  #endif
  58  #ifdef SIGFPE
  59      {"FPE", SIGFPE},
  60  #endif
  61  #ifdef SIGKILL
  62      {"KILL", SIGKILL},
  63  #endif
  64  #ifdef SIGBUS
  65      {"BUS", SIGBUS},
  66  #endif
  67  #ifdef SIGSEGV
  68      {"SEGV", SIGSEGV},
  69  #endif
  70  #ifdef SIGSYS
  71      {"SYS", SIGSYS},
  72  #endif
  73  #ifdef SIGPIPE
  74      {"PIPE", SIGPIPE},
  75  #endif
  76  #ifdef SIGALRM
  77      {"ALRM", SIGALRM},
  78  #endif
  79  #ifdef SIGTERM
  80      {"TERM", SIGTERM},
  81  #endif
  82  #ifdef SIGURG
  83      {"URG", SIGURG},
  84  #endif
  85  #ifdef SIGSTOP
  86      {"STOP", SIGSTOP},
  87  #endif
  88  #ifdef SIGTSTP
  89      {"TSTP", SIGTSTP},
  90  #endif
  91  #ifdef SIGCONT
  92      {"CONT", SIGCONT},
  93  #endif
  94  #ifdef SIGCHLD
  95      {"CHLD", SIGCHLD},
  96  #endif
  97  #ifdef SIGCLD
  98      {"CLD", SIGCLD},
  99  #else
 100  # ifdef SIGCHLD
 101      {"CLD", SIGCHLD},
 102  # endif
 103  #endif
 104  #ifdef SIGTTIN
 105      {"TTIN", SIGTTIN},
 106  #endif
 107  #ifdef SIGTTOU
 108      {"TTOU", SIGTTOU},
 109  #endif
 110  #ifdef SIGIO
 111      {"IO", SIGIO},
 112  #endif
 113  #ifdef SIGXCPU
 114      {"XCPU", SIGXCPU},
 115  #endif
 116  #ifdef SIGXFSZ
 117      {"XFSZ", SIGXFSZ},
 118  #endif
 119  #ifdef SIGVTALRM
 120      {"VTALRM", SIGVTALRM},
 121  #endif
 122  #ifdef SIGPROF
 123      {"PROF", SIGPROF},
 124  #endif
 125  #ifdef SIGWINCH
 126      {"WINCH", SIGWINCH},
 127  #endif
 128  #ifdef SIGUSR1
 129      {"USR1", SIGUSR1},
 130  #endif
 131  #ifdef SIGUSR2
 132      {"USR2", SIGUSR2},
 133  #endif
 134  #ifdef SIGLOST
 135      {"LOST", SIGLOST},
 136  #endif
 137  #ifdef SIGMSG
 138      {"MSG", SIGMSG},
 139  #endif
 140  #ifdef SIGPWR
 141      {"PWR", SIGPWR},
 142  #endif
 143  #ifdef SIGPOLL
 144      {"POLL", SIGPOLL},
 145  #endif
 146  #ifdef SIGDANGER
 147      {"DANGER", SIGDANGER},
 148  #endif
 149  #ifdef SIGMIGRATE
 150      {"MIGRATE", SIGMIGRATE},
 151  #endif
 152  #ifdef SIGPRE
 153      {"PRE", SIGPRE},
 154  #endif
 155  #ifdef SIGGRANT
 156      {"GRANT", SIGGRANT},
 157  #endif
 158  #ifdef SIGRETRACT
 159      {"RETRACT", SIGRETRACT},
 160  #endif
 161  #ifdef SIGSOUND
 162      {"SOUND", SIGSOUND},
 163  #endif
 164  #ifdef SIGINFO
 165      {"INFO", SIGINFO},
 166  #endif
 167      {NULL, 0}
 168  };
 169  
 170  static int
 171  signm2signo(nm)
 172      char *nm;
 173  {
 174      struct signals *sigs;
 175  
 176      for (sigs = siglist; sigs->signm; sigs++)
 177          if (strcmp(sigs->signm, nm) == 0)
 178              return sigs->signo;
 179      return 0;
 180  }
 181  
 182  static char*
 183  signo2signm(no)
 184      int no;
 185  {
 186      struct signals *sigs;
 187  
 188      for (sigs = siglist; sigs->signm; sigs++)
 189          if (sigs->signo == no)
 190              return sigs->signm;
 191      return 0;
 192  }
 193  
 194  VALUE
 195  rb_f_kill(argc, argv)
 196      int argc;
 197      VALUE *argv;
 198  {
 199      int negative = 0;
 200      int sig;
 201      int i;
 202      char *s;
 203  
 204      rb_secure(2);
 205      if (argc < 2)
 206          rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
 207      switch (TYPE(argv[0])) {
 208        case T_FIXNUM:
 209          sig = FIX2INT(argv[0]);
 210          break;
 211  
 212        case T_SYMBOL:
 213          s = rb_id2name(SYM2ID(argv[0]));
 214          if (!s) rb_raise(rb_eArgError, "bad signal");
 215          goto str_signal;
 216  
 217        case T_STRING:
 218          s = RSTRING(argv[0])->ptr;
 219          if (s[0] == '-') {
 220              negative++;
 221              s++;
 222          }
 223        str_signal:
 224          if (strncmp("SIG", s, 3) == 0)
 225              s += 3;
 226          if((sig = signm2signo(s)) == 0)
 227              rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
 228  
 229          if (negative)
 230              sig = -sig;
 231          break;
 232  
 233        default:
 234          {
 235              VALUE str;
 236  
 237              str = rb_check_convert_type(argv[0], T_STRING, "String", "to_str");
 238              if (!NIL_P(str)) {
 239                  s = RSTRING(str)->ptr;
 240                  goto str_signal;
 241              }
 242              rb_raise(rb_eArgError, "bad signal type %s",
 243                       rb_class2name(CLASS_OF(argv[0])));
 244          }
 245          break;
 246      }
 247  
 248      if (sig < 0) {
 249          sig = -sig;
 250          for (i=1; i<argc; i++) {
 251              int pid = NUM2INT(argv[i]);
 252  #ifdef HAS_KILLPG
 253              if (killpg(pid, sig) < 0)
 254  #else
 255              if (kill(-pid, sig) < 0)
 256  #endif
 257                  rb_sys_fail(0);
 258          }
 259      }
 260      else {
 261          for (i=1; i<argc; i++) {
 262              Check_Type(argv[i], T_FIXNUM);
 263              if (kill(FIX2INT(argv[i]), sig) < 0)
 264                  rb_sys_fail(0);
 265          }
 266      }
 267      return INT2FIX(i-1);
 268  }
 269  
 270  static VALUE trap_list[NSIG];
 271  static rb_atomic_t trap_pending_list[NSIG];
 272  rb_atomic_t rb_trap_pending;
 273  rb_atomic_t rb_trap_immediate;
 274  int rb_prohibit_interrupt;
 275  
 276  void
 277  rb_gc_mark_trap_list()
 278  {
 279  #ifndef MACOS_UNUSE_SIGNAL
 280      int i;
 281  
 282      for (i=0; i<NSIG; i++) {
 283          if (trap_list[i])
 284              rb_gc_mark(trap_list[i]);
 285      }
 286  #endif /* MACOS_UNUSE_SIGNAL */
 287  }
 288  
 289  #ifdef __dietlibc__
 290  #define sighandler_t sh_t
 291  #endif
 292  
 293  typedef RETSIGTYPE (*sighandler_t)_((int));
 294  
 295  #ifdef POSIX_SIGNAL
 296  static sighandler_t
 297  ruby_signal(signum, handler)
 298      int signum;
 299      sighandler_t handler;
 300  {
 301      struct sigaction sigact, old;
 302  
 303      sigact.sa_handler = handler;
 304      sigemptyset(&sigact.sa_mask);
 305      sigact.sa_flags = 0;
 306  #if defined(SA_RESTART)
 307      /* All other signals but VTALRM shall restart restartable syscall
 308         VTALRM will cause EINTR to syscall if interrupted.
 309      */
 310      if (signum != SIGVTALRM) {
 311          sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
 312      }
 313  #endif
 314  #ifdef SA_NOCLDWAIT
 315      if (signum == SIGCHLD && handler == SIG_IGN)
 316          sigact.sa_flags |= SA_NOCLDWAIT;
 317  #endif
 318      sigaction(signum, &sigact, &old);
 319      return old.sa_handler;
 320  }
 321  
 322  void
 323  posix_signal(signum, handler)
 324      int signum;
 325      sighandler_t handler;
 326  {
 327      ruby_signal(signum, handler);
 328  }
 329  #else
 330  #define ruby_signal(sig,handler) signal((sig),(handler))
 331  #endif
 332  
 333  static void signal_exec _((int sig));
 334  static void
 335  signal_exec(sig)
 336      int sig;
 337  {
 338      if (trap_list[sig] == 0) {
 339          switch (sig) {
 340            case SIGINT:
 341              rb_thread_interrupt();
 342              break;
 343  #ifdef SIGHUP
 344            case SIGHUP:
 345  #endif
 346  #ifdef SIGQUIT
 347            case SIGQUIT:
 348  #endif
 349  #ifdef SIGALRM
 350            case SIGALRM:
 351  #endif
 352  #ifdef SIGUSR1
 353            case SIGUSR1:
 354  #endif
 355  #ifdef SIGUSR2
 356            case SIGUSR2:
 357  #endif
 358              rb_thread_signal_raise(signo2signm(sig));
 359              break;
 360          }
 361      }
 362      else {
 363          rb_thread_trap_eval(trap_list[sig], sig);
 364      }
 365  }
 366  
 367  static RETSIGTYPE sighandler _((int));
 368  static RETSIGTYPE
 369  sighandler(sig)
 370      int sig;
 371  {
 372  #ifdef NT
 373  #define IN_MAIN_CONTEXT(f, a) (rb_w32_main_context(a, f) ? (void)0 : f(a))
 374  #else
 375  #define IN_MAIN_CONTEXT(f, a) f(a)
 376  #endif
 377  
 378      if (sig >= NSIG) {
 379          rb_bug("trap_handler: Bad signal %d", sig);
 380      }
 381  
 382  #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
 383      ruby_signal(sig, sighandler);
 384  #endif
 385  
 386      if (ATOMIC_TEST(rb_trap_immediate)) {
 387          IN_MAIN_CONTEXT(signal_exec, sig);
 388          ATOMIC_SET(rb_trap_immediate, 1);
 389      }
 390      else {
 391          ATOMIC_INC(rb_trap_pending);
 392          ATOMIC_INC(trap_pending_list[sig]);
 393      }
 394  }
 395  
 396  #ifdef SIGBUS
 397  static RETSIGTYPE sigbus _((int));
 398  static RETSIGTYPE
 399  sigbus(sig)
 400      int sig;
 401  {
 402      rb_bug("Bus Error");
 403  }
 404  #endif
 405  
 406  #ifdef SIGSEGV
 407  static RETSIGTYPE sigsegv _((int));
 408  static RETSIGTYPE
 409  sigsegv(sig)
 410      int sig;
 411  {
 412      rb_bug("Segmentation fault");
 413  }
 414  #endif
 415  
 416  #ifdef SIGPIPE
 417  static RETSIGTYPE sigpipe _((int));
 418  static RETSIGTYPE
 419  sigpipe(sig)
 420      int sig;
 421  {
 422      /* do nothing */
 423  }
 424  #endif
 425  
 426  void
 427  rb_trap_exit()
 428  {
 429  #ifndef MACOS_UNUSE_SIGNAL
 430      if (trap_list[0]) {
 431          VALUE trap_exit = trap_list[0];
 432  
 433          trap_list[0] = 0;
 434          rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), 0);
 435      }
 436  #endif
 437  }
 438  
 439  void
 440  rb_trap_exec()
 441  {
 442  #ifndef MACOS_UNUSE_SIGNAL
 443      int i;
 444  
 445      for (i=0; i<NSIG; i++) {
 446          if (trap_pending_list[i]) {
 447              trap_pending_list[i] = 0;
 448              signal_exec(i);
 449          }
 450      }
 451  #endif /* MACOS_UNUSE_SIGNAL */
 452      rb_trap_pending = 0;
 453  }
 454  
 455  struct trap_arg {
 456  #if !defined(NT)
 457  # ifdef HAVE_SIGPROCMASK
 458      sigset_t mask;
 459  # else
 460      int mask;
 461  # endif
 462  #endif
 463      VALUE sig, cmd;
 464  };
 465  
 466  # ifdef HAVE_SIGPROCMASK
 467  static sigset_t trap_last_mask;
 468  # else
 469  static int trap_last_mask;
 470  # endif
 471  
 472  static RETSIGTYPE sigexit _((int));
 473  static RETSIGTYPE
 474  sigexit(sig)
 475      int sig;
 476  {
 477      rb_exit(0);
 478  }
 479  
 480  static VALUE
 481  trap(arg)
 482      struct trap_arg *arg;
 483  {
 484      sighandler_t func;
 485      VALUE command, old;
 486      int sig = -1;
 487      char *s;
 488  
 489      func = sighandler;
 490      command = arg->cmd;
 491      if (NIL_P(command)) {
 492          func = SIG_IGN;
 493      }
 494      else if (TYPE(command) == T_STRING) {
 495          SafeStringValue(command);       /* taint check */
 496          if (RSTRING(command)->len == 0) {
 497              func = SIG_IGN;
 498          }
 499          else if (RSTRING(command)->len == 7) {
 500              if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) {
 501                  func = SIG_IGN;
 502              }
 503              else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) {
 504                  func = SIG_DFL;
 505              }
 506              else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) {
 507                  func = SIG_DFL;
 508              }
 509          }
 510          else if (RSTRING(command)->len == 6) {
 511              if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) {
 512                  func = SIG_IGN;
 513              }
 514          }
 515          else if (RSTRING(command)->len == 4) {
 516              if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) {
 517                  func = sigexit;
 518              }
 519          }
 520      }
 521      if (func == SIG_IGN || func == SIG_DFL) {
 522          command = 0;
 523      }
 524  
 525      switch (TYPE(arg->sig)) {
 526        case T_FIXNUM:
 527          sig = NUM2INT(arg->sig);
 528          break;
 529  
 530        case T_SYMBOL:
 531          s = rb_id2name(SYM2ID(arg->sig));
 532          if (!s) rb_raise(rb_eArgError, "bad signal");
 533          goto str_signal;
 534  
 535        case T_STRING:
 536          s = RSTRING(arg->sig)->ptr;
 537  
 538        str_signal:
 539          if (strncmp("SIG", s, 3) == 0)
 540              s += 3;
 541          sig = signm2signo(s);
 542          if (sig == 0 && strcmp(s, "EXIT") != 0)
 543              rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
 544      }
 545  
 546      if (sig < 0 || sig > NSIG) {
 547          rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
 548      }
 549  #if defined(HAVE_SETITIMER) && !defined(__BOW__)
 550      if (sig == SIGVTALRM) {
 551          rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; cannot set handler");
 552      }
 553  #endif
 554      if (func == SIG_DFL) {
 555          switch (sig) {
 556            case SIGINT:
 557  #ifdef SIGHUP
 558            case SIGHUP:
 559  #endif
 560  #ifdef SIGQUIT
 561            case SIGQUIT:
 562  #endif
 563  #ifdef SIGALRM
 564            case SIGALRM:
 565  #endif
 566  #ifdef SIGUSR1
 567            case SIGUSR1:
 568  #endif
 569  #ifdef SIGUSR2
 570            case SIGUSR2:
 571  #endif
 572              func = sighandler;
 573              break;
 574  #ifdef SIGBUS
 575            case SIGBUS:
 576              func = sigbus;
 577              break;
 578  #endif
 579  #ifdef SIGSEGV
 580            case SIGSEGV:
 581              func = sigsegv;
 582              break;
 583  #endif
 584  #ifdef SIGPIPE
 585            case SIGPIPE:
 586              func = sigpipe;
 587              break;
 588  #endif
 589          }
 590      }
 591      ruby_signal(sig, func);
 592      old = trap_list[sig];
 593      if (!old) old = Qnil;
 594  
 595      trap_list[sig] = command;
 596      /* enable at least specified signal. */
 597  #if !defined(NT)
 598  #ifdef HAVE_SIGPROCMASK
 599      sigdelset(&arg->mask, sig);
 600  #else
 601      arg->mask &= ~sigmask(sig);
 602  #endif
 603  #endif
 604      return old;
 605  }
 606  
 607  #if !defined(NT)
 608  static VALUE
 609  trap_ensure(arg)
 610      struct trap_arg *arg;
 611  {
 612      /* enable interrupt */
 613  #ifdef HAVE_SIGPROCMASK
 614      sigprocmask(SIG_SETMASK, &arg->mask, NULL);
 615  #else
 616      sigsetmask(arg->mask);
 617  #endif
 618      trap_last_mask = arg->mask;
 619      return 0;
 620  }
 621  #endif
 622  
 623  void
 624  rb_trap_restore_mask()
 625  {
 626  #if !defined(NT)
 627  # ifdef HAVE_SIGPROCMASK
 628      sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
 629  # else
 630      sigsetmask(trap_last_mask);
 631  # endif
 632  #endif
 633  }
 634  
 635  static VALUE
 636  sig_trap(argc, argv)
 637      int argc;
 638      VALUE *argv;
 639  {
 640      struct trap_arg arg;
 641  
 642      rb_secure(2);
 643      if (argc == 0 || argc > 2) {
 644          rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
 645      }
 646  
 647      arg.sig = argv[0];
 648      if (argc == 1) {
 649          arg.cmd = rb_f_lambda();
 650      }
 651      else if (argc == 2) {
 652          arg.cmd = argv[1];
 653      }
 654  
 655      if (OBJ_TAINTED(arg.cmd)) {
 656          rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
 657      }
 658  #if !defined(NT)
 659      /* disable interrupt */
 660  # ifdef HAVE_SIGPROCMASK
 661      sigfillset(&arg.mask);
 662      sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
 663  # else
 664      arg.mask = sigblock(~0);
 665  # endif
 666  
 667      return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
 668  #else
 669      return trap(&arg);
 670  #endif
 671  }
 672  
 673  static VALUE
 674  sig_list()
 675  {
 676      VALUE h = rb_hash_new();
 677      struct signals *sigs;
 678  
 679      for (sigs = siglist; sigs->signm; sigs++) {
 680          rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
 681      }
 682      return h;
 683  }
 684  
 685  static void
 686  install_sighandler(signum, handler)
 687      int signum;
 688      sighandler_t handler;
 689  {
 690      sighandler_t old;
 691  
 692      old = ruby_signal(signum, handler);
 693      if (old != SIG_DFL) {
 694          ruby_signal(signum, old);
 695      }
 696  }
 697  
 698  void
 699  Init_signal()
 700  {
 701  #ifndef MACOS_UNUSE_SIGNAL
 702      VALUE mSignal = rb_define_module("Signal");
 703  
 704      rb_define_global_function("trap", sig_trap, -1);
 705      rb_define_module_function(mSignal, "trap", sig_trap, -1);
 706      rb_define_module_function(mSignal, "list", sig_list, 0);
 707  
 708      install_sighandler(SIGINT, sighandler);
 709  #ifdef SIGHUP
 710      install_sighandler(SIGHUP, sighandler);
 711  #endif
 712  #ifdef SIGQUIT
 713      install_sighandler(SIGQUIT, sighandler);
 714  #endif
 715  #ifdef SIGALRM
 716      install_sighandler(SIGALRM, sighandler);
 717  #endif
 718  #ifdef SIGUSR1
 719      install_sighandler(SIGUSR1, sighandler);
 720  #endif
 721  #ifdef SIGUSR2
 722      install_sighandler(SIGUSR2, sighandler);
 723  #endif
 724  
 725  #ifdef SIGBUS
 726      install_sighandler(SIGBUS, sigbus);
 727  #endif
 728  #ifdef SIGSEGV
 729      install_sighandler(SIGSEGV, sigsegv);
 730  #endif
 731  #ifdef SIGPIPE
 732      install_sighandler(SIGPIPE, sigpipe);
 733  #endif
 734  #endif /* MACOS_UNUSE_SIGNAL */
 735  }