1. my enum Signal ( :SIGHUP(1), :SIGINT(2), :SIGQUIT(3), :SIGILL(4), :SIGTRAP(5),
  2. :SIGABRT(6), :SIGEMT(7), :SIGFPE(8), :SIGKILL(9), :SIGBUS(10), :SIGSEGV(11),
  3. :SIGSYS(12), :SIGPIPE(13), :SIGALRM(14), :SIGTERM(15), :SIGURG(16),
  4. :SIGSTOP(17), :SIGTSTP(18), :SIGCONT(19), :SIGCHLD(20), :SIGTTIN(21),
  5. :SIGTTOU(22), :SIGIO(23), :SIGXCPU(24), :SIGXFSZ(25), :SIGVTALRM(26),
  6. :SIGPROF(27), :SIGWINCH(28), :SIGINFO(29), :SIGUSR1(30), :SIGUSR2(31),
  7. :SIGTHR(32), :SIGSTKFLT(116), :SIGPWR(130), :SIGBREAK(221) );
  8. proto sub signal(|) {*}
  9. multi sub signal(Signal $signal, *@signals, :$scheduler = $*SCHEDULER) {
  10. if @signals.grep( { !nqp::istype($_,Signal) } ).list -> @invalid {
  11. die "Found invalid signals: {@invalid}";
  12. }
  13. @signals.unshift: $signal;
  14. @signals .= unique;
  15. my constant %sigmap = (
  16. SIGHUP, nqp::const::SIG_HUP,
  17. SIGINT, nqp::const::SIG_INT,
  18. SIGQUIT, nqp::const::SIG_QUIT,
  19. SIGILL, nqp::const::SIG_ILL,
  20. SIGTRAP, nqp::const::SIG_TRAP,
  21. SIGABRT, nqp::const::SIG_ABRT,
  22. SIGEMT, nqp::const::SIG_EMT,
  23. SIGFPE, nqp::const::SIG_FPE,
  24. SIGKILL, nqp::const::SIG_KILL,
  25. SIGBUS, nqp::const::SIG_BUS,
  26. SIGSEGV, nqp::const::SIG_SEGV,
  27. SIGSYS, nqp::const::SIG_SYS,
  28. SIGPIPE, nqp::const::SIG_PIPE,
  29. SIGALRM, nqp::const::SIG_ALRM,
  30. SIGTERM, nqp::const::SIG_TERM,
  31. SIGURG, nqp::const::SIG_URG,
  32. SIGSTOP, nqp::const::SIG_STOP, # hammer time
  33. SIGTSTP, nqp::const::SIG_TSTP,
  34. SIGCONT, nqp::const::SIG_CONT,
  35. SIGCHLD, nqp::const::SIG_CHLD,
  36. SIGTTIN, nqp::const::SIG_TTIN,
  37. SIGTTOU, nqp::const::SIG_TTOU,
  38. SIGIO, nqp::const::SIG_IO,
  39. SIGXCPU, nqp::const::SIG_XCPU,
  40. SIGXFSZ, nqp::const::SIG_XFSZ,
  41. SIGVTALRM,nqp::const::SIG_VTALRM,
  42. SIGPROF, nqp::const::SIG_PROF,
  43. SIGWINCH, nqp::const::SIG_WINCH,
  44. SIGINFO, nqp::const::SIG_INFO,
  45. SIGUSR1, nqp::const::SIG_USR1,
  46. SIGUSR2, nqp::const::SIG_USR2,
  47. SIGTHR, nqp::const::SIG_THR,
  48. SIGSTKFLT,nqp::const::SIG_STKFLT,
  49. SIGPWR, nqp::const::SIG_PWR,
  50. SIGBREAK, nqp::const::SIG_BREAK
  51. ).hash;
  52. my @known_signals := $*KERNEL.signals;
  53. my class SignalCancellation is repr('AsyncTask') { }
  54. Supply.merge( @signals.map(-> $signal {
  55. class SignalTappable does Tappable {
  56. has $!scheduler;
  57. has @!known_signals;
  58. has %!sigmap;
  59. has $!signal;
  60. submethod BUILD(:$!scheduler, :@!known_signals, :%!sigmap, :$!signal) { }
  61. method tap(&emit, &, &, &tap) {
  62. my $cancellation := nqp::signal($!scheduler.queue(:hint-time-sensitive),
  63. -> $signum { emit(@!known_signals[$signum] // $signum) },
  64. nqp::unbox_i(%!sigmap{$!signal}),
  65. SignalCancellation);
  66. my $t = Tap.new({ nqp::cancel($cancellation) });
  67. tap($t);
  68. $t;
  69. }
  70. method live(--> False) { }
  71. method sane(--> True) { }
  72. method serial(--> False) { }
  73. }
  74. Supply.new(SignalTappable.new(:$scheduler, :@known_signals, :%sigmap, :$signal));
  75. }) );
  76. }