| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | // Fix signal macro compatibility with signal.h of MS VC++: | 
| 4 |  |  |  |  |  |  | #ifdef WIN32 | 
| 5 |  |  |  |  |  |  | #define signal win32_signal | 
| 6 |  |  |  |  |  |  | #endif | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | #include | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | // Get back Perl marcro value defined ad XSUB.h: | 
| 11 |  |  |  |  |  |  | #ifdef WIN32 | 
| 12 |  |  |  |  |  |  | #define signal PerlProc_signal | 
| 13 |  |  |  |  |  |  | #endif | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | #endif | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | static struct pe_watcher_vtbl pe_signal_vtbl; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | /* GLOBALS: Sigvalid Sigring Sigstat Sigslot */ | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | static U32 Sigvalid[1+NSIG/32]; /*assume 32bit; doesn't matter*/ | 
| 22 |  |  |  |  |  |  | #define PE_SIGVALID(sig)  	(Sigvalid[sig>>5] & (1 << ((sig) & 0x1f))) | 
| 23 |  |  |  |  |  |  | #define PE_SIGVALID_off(sig)	Sigvalid[sig>>5] &= ~(1 << ((sig) & 0x1f)) | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | struct pe_sig_stat { | 
| 26 |  |  |  |  |  |  | U32 Hits; | 
| 27 |  |  |  |  |  |  | U16 hits[NSIG]; | 
| 28 |  |  |  |  |  |  | }; | 
| 29 |  |  |  |  |  |  | typedef struct pe_sig_stat pe_sig_stat; | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | static int Sigslot; | 
| 32 |  |  |  |  |  |  | static pe_sig_stat Sigstat[2]; | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | static pe_ring Sigring[NSIG]; | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | /* /GLOBALS */ | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 2 |  |  |  |  |  | static Signal_t process_sighandler(int sig) { | 
| 39 | 2 |  |  |  |  |  | pe_sig_stat *st = &Sigstat[Sigslot]; | 
| 40 | 2 |  |  |  |  |  | ++st->Hits; | 
| 41 | 2 |  |  |  |  |  | ++st->hits[sig]; | 
| 42 | 2 |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  |  | 
| 44 | 4 |  |  |  |  |  | static pe_watcher *pe_signal_allocate(HV *stash, SV *temple) { | 
| 45 |  |  |  |  |  |  | pe_signal *ev; | 
| 46 | 4 |  |  |  |  |  | EvNew(5, ev, 1, pe_signal); | 
| 47 | 4 |  |  |  |  |  | ev->base.vtbl = &pe_signal_vtbl; | 
| 48 | 4 |  |  |  |  |  | PE_RING_INIT(&ev->sring, ev); | 
| 49 | 4 |  |  |  |  |  | ev->signal = 0; | 
| 50 | 4 |  |  |  |  |  | pe_watcher_init(&ev->base, stash, temple); | 
| 51 | 4 |  |  |  |  |  | WaREPEAT_on(ev); | 
| 52 | 4 |  |  |  |  |  | WaINVOKE1_off(ev); | 
| 53 | 4 |  |  |  |  |  | return (pe_watcher*) ev; | 
| 54 |  |  |  |  |  |  | } | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 4 |  |  |  |  |  | static void pe_signal_dtor(pe_watcher *ev) { | 
| 57 | 4 |  |  |  |  |  | pe_watcher_dtor(ev); | 
| 58 | 4 |  |  |  |  |  | EvFree(5, ev); | 
| 59 | 4 |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 2 |  |  |  |  |  | static char *pe_signal_start(pe_watcher *_ev, int repeat) { | 
| 62 | 2 |  |  |  |  |  | pe_signal *ev = (pe_signal*) _ev; | 
| 63 | 2 |  |  |  |  |  | int sig = ev->signal; | 
| 64 | 2 | 50 |  |  |  |  | if (!_ev->callback) | 
| 65 | 0 |  |  |  |  |  | return "without callback"; | 
| 66 | 2 | 100 |  |  |  |  | if (sig == 0) | 
| 67 | 1 |  |  |  |  |  | return "without signal"; | 
| 68 | 1 | 50 |  |  |  |  | if (PE_RING_EMPTY(&Sigring[sig])) | 
| 69 | 1 |  |  |  |  |  | rsignal(sig, (Sighandler_t)process_sighandler); | 
| 70 | 1 |  |  |  |  |  | PE_RING_UNSHIFT(&ev->sring, &Sigring[sig]); | 
| 71 | 1 |  |  |  |  |  | return 0; | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 1 |  |  |  |  |  | static void pe_signal_stop(pe_watcher *_ev) { | 
| 75 | 1 |  |  |  |  |  | pe_signal *ev = (pe_signal*) _ev; | 
| 76 | 1 |  |  |  |  |  | int sig = ev->signal; | 
| 77 | 1 | 50 |  |  |  |  | PE_RING_DETACH(&ev->sring); | 
| 78 | 1 | 50 |  |  |  |  | if (PE_RING_EMPTY(&Sigring[sig])) { | 
| 79 | 1 |  |  |  |  |  | rsignal(sig, (Sighandler_t)SIG_DFL); | 
| 80 | 1 |  |  |  |  |  | Sigstat[0].hits[sig] = 0; | 
| 81 | 1 |  |  |  |  |  | Sigstat[1].hits[sig] = 0; | 
| 82 |  |  |  |  |  |  | } | 
| 83 | 1 |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 2 |  |  |  |  |  | WKEYMETH(_signal_signal) { | 
| 86 | 2 |  |  |  |  |  | pe_signal *sg = (pe_signal*) ev; | 
| 87 | 2 | 100 |  |  |  |  | if (nval) { | 
| 88 |  |  |  |  |  |  | STRLEN n_a; | 
| 89 | 1 |  |  |  |  |  | int active = WaPOLLING(ev); | 
| 90 | 1 | 50 |  |  |  |  | int sig = whichsig(SvPV(nval, n_a)); | 
| 91 |  |  |  |  |  |  | /*warn("whichsig(%s) = %d", SvPV(nval,na), sig); /**/ | 
| 92 | 1 | 50 |  |  |  |  | if (sig == 0) | 
| 93 | 0 | 0 |  |  |  |  | croak("Unrecognized signal '%s'", SvPV(nval, n_a)); | 
| 94 | 1 | 50 |  |  |  |  | if (!PE_SIGVALID(sig)) | 
| 95 | 0 | 0 |  |  |  |  | croak("Signal '%s' cannot be caught", SvPV(nval, n_a)); | 
| 96 | 1 | 50 |  |  |  |  | if (active) pe_watcher_off(ev); | 
| 97 | 1 |  |  |  |  |  | sg->signal = sig; | 
| 98 | 1 | 50 |  |  |  |  | if (active) pe_watcher_on(ev, 0); | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  | { | 
| 101 | 2 |  |  |  |  |  | dSP; | 
| 102 | 2 | 50 |  |  |  |  | XPUSHs(sg->signal > 0? | 
|  |  | 50 |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | sv_2mortal(newSVpv(PL_sig_name[sg->signal],0)) : &PL_sv_undef); | 
| 104 | 2 |  |  |  |  |  | PUTBACK; | 
| 105 |  |  |  |  |  |  | } | 
| 106 | 2 |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 | 1 |  |  |  |  |  | static void _signal_asynccheck(pe_sig_stat *st) { | 
| 109 |  |  |  |  |  |  | int xx, got; | 
| 110 |  |  |  |  |  |  | pe_watcher *wa; | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 65 | 100 |  |  |  |  | for (xx = 1; xx < NSIG; xx++) { | 
| 113 | 64 | 100 |  |  |  |  | if (!st->hits[xx]) | 
| 114 | 63 |  |  |  |  |  | continue; | 
| 115 | 1 |  |  |  |  |  | got = st->hits[xx]; | 
| 116 | 1 |  |  |  |  |  | wa = (pe_watcher*) Sigring[xx].next->self; | 
| 117 | 2 | 100 |  |  |  |  | while (wa) { | 
| 118 | 1 |  |  |  |  |  | pe_event *ev = (*wa->vtbl->new_event)(wa); | 
| 119 | 1 |  |  |  |  |  | ev->hits += got; | 
| 120 | 1 |  |  |  |  |  | queueEvent(ev); | 
| 121 | 1 |  |  |  |  |  | wa = (pe_watcher*) ((pe_signal*)wa)->sring.next->self; | 
| 122 |  |  |  |  |  |  | } | 
| 123 | 1 |  |  |  |  |  | st->hits[xx] = 0; | 
| 124 |  |  |  |  |  |  | } | 
| 125 | 1 |  |  |  |  |  | Zero(st, 1, struct pe_sig_stat); | 
| 126 | 1 |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | /* This implementation gives no race conditions, assuming | 
| 129 |  |  |  |  |  |  | no kernel-level threads. */ | 
| 130 | 164634 |  |  |  |  |  | static void pe_signal_asynccheck() { | 
| 131 |  |  |  |  |  |  | pe_sig_stat *st; | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 164634 |  |  |  |  |  | Sigslot = 1; | 
| 134 | 164634 |  |  |  |  |  | st = &Sigstat[0]; | 
| 135 | 164634 | 100 |  |  |  |  | if (st->Hits) _signal_asynccheck(st); | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 164634 |  |  |  |  |  | Sigslot = 0; | 
| 138 | 164634 |  |  |  |  |  | st = &Sigstat[1]; | 
| 139 | 164634 | 50 |  |  |  |  | if (st->Hits) _signal_asynccheck(st); | 
| 140 | 164634 |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 25 |  |  |  |  |  | static void boot_signal() { | 
| 143 |  |  |  |  |  |  | int xx; | 
| 144 |  |  |  |  |  |  | int sig; | 
| 145 |  |  |  |  |  |  | char **sigp; | 
| 146 |  |  |  |  |  |  | /* it is crufty to hardcode this list */ | 
| 147 |  |  |  |  |  |  | static char *nohandle[] = { "KILL", "STOP", "ZERO", 0 }; | 
| 148 | 25 |  |  |  |  |  | pe_watcher_vtbl *vt = &pe_signal_vtbl; | 
| 149 | 25 |  |  |  |  |  | Zero(&Sigstat[0], 1, pe_sig_stat); | 
| 150 | 25 |  |  |  |  |  | Zero(&Sigstat[1], 1, pe_sig_stat); | 
| 151 | 25 |  |  |  |  |  | Sigslot = 0; | 
| 152 | 1650 | 100 |  |  |  |  | for (xx=0; xx < NSIG; xx++) { | 
| 153 | 1625 |  |  |  |  |  | PE_RING_INIT(&Sigring[xx], 0); | 
| 154 |  |  |  |  |  |  | } | 
| 155 | 25 |  |  |  |  |  | memset(Sigvalid, ~0, sizeof(Sigvalid)); | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 25 |  |  |  |  |  | PE_SIGVALID_off(0); | 
| 158 | 25 |  |  |  |  |  | sigp = nohandle; | 
| 159 | 100 | 100 |  |  |  |  | while (*sigp) { | 
| 160 | 75 |  |  |  |  |  | sig = whichsig(*sigp); | 
| 161 | 75 | 100 |  |  |  |  | if (sig) PE_SIGVALID_off(sig); | 
| 162 | 75 |  |  |  |  |  | ++sigp; | 
| 163 |  |  |  |  |  |  | } | 
| 164 | 25 |  |  |  |  |  | memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); | 
| 165 | 25 |  |  |  |  |  | vt->dtor = pe_signal_dtor; | 
| 166 | 25 |  |  |  |  |  | vt->start = pe_signal_start; | 
| 167 | 25 |  |  |  |  |  | vt->stop = pe_signal_stop; | 
| 168 | 25 |  |  |  |  |  | pe_register_vtbl(vt, gv_stashpv("Event::signal",1), &event_vtbl); | 
| 169 | 25 |  |  |  |  |  | } |