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
|
193350
|
|
|
|
|
|
static void pe_signal_asynccheck() { |
131
|
|
|
|
|
|
|
pe_sig_stat *st; |
132
|
|
|
|
|
|
|
|
133
|
193350
|
|
|
|
|
|
Sigslot = 1; |
134
|
193350
|
|
|
|
|
|
st = &Sigstat[0]; |
135
|
193350
|
100
|
|
|
|
|
if (st->Hits) _signal_asynccheck(st); |
136
|
|
|
|
|
|
|
|
137
|
193350
|
|
|
|
|
|
Sigslot = 0; |
138
|
193350
|
|
|
|
|
|
st = &Sigstat[1]; |
139
|
193350
|
50
|
|
|
|
|
if (st->Hits) _signal_asynccheck(st); |
140
|
193350
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
24
|
|
|
|
|
|
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
|
24
|
|
|
|
|
|
pe_watcher_vtbl *vt = &pe_signal_vtbl; |
149
|
24
|
|
|
|
|
|
Zero(&Sigstat[0], 1, pe_sig_stat); |
150
|
24
|
|
|
|
|
|
Zero(&Sigstat[1], 1, pe_sig_stat); |
151
|
24
|
|
|
|
|
|
Sigslot = 0; |
152
|
1584
|
100
|
|
|
|
|
for (xx=0; xx < NSIG; xx++) { |
153
|
1560
|
|
|
|
|
|
PE_RING_INIT(&Sigring[xx], 0); |
154
|
|
|
|
|
|
|
} |
155
|
24
|
|
|
|
|
|
memset(Sigvalid, ~0, sizeof(Sigvalid)); |
156
|
|
|
|
|
|
|
|
157
|
24
|
|
|
|
|
|
PE_SIGVALID_off(0); |
158
|
24
|
|
|
|
|
|
sigp = nohandle; |
159
|
96
|
100
|
|
|
|
|
while (*sigp) { |
160
|
72
|
|
|
|
|
|
sig = whichsig(*sigp); |
161
|
72
|
100
|
|
|
|
|
if (sig) PE_SIGVALID_off(sig); |
162
|
72
|
|
|
|
|
|
++sigp; |
163
|
|
|
|
|
|
|
} |
164
|
24
|
|
|
|
|
|
memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); |
165
|
24
|
|
|
|
|
|
vt->dtor = pe_signal_dtor; |
166
|
24
|
|
|
|
|
|
vt->start = pe_signal_start; |
167
|
24
|
|
|
|
|
|
vt->stop = pe_signal_stop; |
168
|
24
|
|
|
|
|
|
pe_register_vtbl(vt, gv_stashpv("Event::signal",1), &event_vtbl); |
169
|
24
|
|
|
|
|
|
} |