1 | #include "EXTERN.h" |
1 | #include "EXTERN.h" |
2 | #include "perl.h" |
2 | #include "perl.h" |
3 | #include "XSUB.h" |
3 | #include "XSUB.h" |
|
|
4 | |
|
|
5 | #include "schmorp.h" |
4 | |
6 | |
5 | typedef volatile sig_atomic_t atomic_t; |
7 | typedef volatile sig_atomic_t atomic_t; |
6 | |
8 | |
7 | static int *sig_pending, *psig_pend; /* make local copies because of missing THX */ |
9 | static int *sig_pending, *psig_pend; /* make local copies because of missing THX */ |
8 | static Sighandler_t old_sighandler; |
10 | static Sighandler_t old_sighandler; |
… | |
… | |
19 | #endif |
21 | #endif |
20 | |
22 | |
21 | #if !PERL_VERSION_ATLEAST(5,10,0) |
23 | #if !PERL_VERSION_ATLEAST(5,10,0) |
22 | # undef HAS_SA_SIGINFO |
24 | # undef HAS_SA_SIGINFO |
23 | #endif |
25 | #endif |
24 | |
|
|
25 | /*****************************************************************************/ |
|
|
26 | /* support stuff, copied from EV.xs mostly */ |
|
|
27 | |
|
|
28 | static int |
|
|
29 | extract_fd (SV *fh, int wr) |
|
|
30 | { |
|
|
31 | int fd = PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh))); |
|
|
32 | |
|
|
33 | if (fd < 0) |
|
|
34 | croak ("illegal fh argument, either not an OS file or read/write mode mismatch"); |
|
|
35 | |
|
|
36 | return fd; |
|
|
37 | } |
|
|
38 | |
|
|
39 | static SV * |
|
|
40 | get_cb (SV *cb_sv) |
|
|
41 | { |
|
|
42 | HV *st; |
|
|
43 | GV *gvp; |
|
|
44 | CV *cv; |
|
|
45 | |
|
|
46 | if (!SvOK (cb_sv)) |
|
|
47 | return 0; |
|
|
48 | |
|
|
49 | cv = sv_2cv (cb_sv, &st, &gvp, 0); |
|
|
50 | |
|
|
51 | if (!cv) |
|
|
52 | croak ("Async::Interrupt callback must be undef or a CODE reference"); |
|
|
53 | |
|
|
54 | return (SV *)cv; |
|
|
55 | } |
|
|
56 | |
|
|
57 | #ifndef SIG_SIZE |
|
|
58 | /* kudos to Slaven Rezic for the idea */ |
|
|
59 | static char sig_size [] = { SIG_NUM }; |
|
|
60 | # define SIG_SIZE (sizeof (sig_size) + 1) |
|
|
61 | #endif |
|
|
62 | |
|
|
63 | static int |
|
|
64 | sv_signum (SV *sig) |
|
|
65 | { |
|
|
66 | int signum; |
|
|
67 | |
|
|
68 | SvGETMAGIC (sig); |
|
|
69 | |
|
|
70 | for (signum = 1; signum < SIG_SIZE; ++signum) |
|
|
71 | if (strEQ (SvPV_nolen (sig), PL_sig_name [signum])) |
|
|
72 | return signum; |
|
|
73 | |
|
|
74 | signum = SvIV (sig); |
|
|
75 | |
|
|
76 | if (signum > 0 && signum < SIG_SIZE) |
|
|
77 | return signum; |
|
|
78 | |
|
|
79 | return -1; |
|
|
80 | } |
|
|
81 | |
26 | |
82 | /*****************************************************************************/ |
27 | /*****************************************************************************/ |
83 | |
28 | |
84 | typedef struct { |
29 | typedef struct { |
85 | SV *cb; |
30 | SV *cb; |
… | |
… | |
266 | |
211 | |
267 | void |
212 | void |
268 | _alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w, SV *signl) |
213 | _alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w, SV *signl) |
269 | PPCODE: |
214 | PPCODE: |
270 | { |
215 | { |
271 | SV *cv = SvOK (cb) ? SvREFCNT_inc (get_cb (cb)) : 0; |
216 | SV *cv = SvOK (cb) ? SvREFCNT_inc (s_get_cv_croak (cb)) : 0; |
272 | int fd_r = SvOK (fh_r) ? extract_fd (fh_r, 0) : -1; |
217 | int fd_r = SvOK (fh_r) ? s_fileno_croak (fh_r, 0) : -1; |
273 | int fd_w = SvOK (fh_w) ? extract_fd (fh_w, 1) : -1; |
218 | int fd_w = SvOK (fh_w) ? s_fileno_croak (fh_w, 1) : -1; |
274 | async_t *async; |
219 | async_t *async; |
275 | |
220 | |
276 | Newz (0, async, 1, async_t); |
221 | Newz (0, async, 1, async_t); |
277 | |
222 | |
278 | XPUSHs (sv_2mortal (newSViv (PTR2IV (async)))); |
223 | XPUSHs (sv_2mortal (newSViv (PTR2IV (async)))); |
… | |
… | |
283 | async->fd_wlen = 1; |
228 | async->fd_wlen = 1; |
284 | async->fd_enable = 1; |
229 | async->fd_enable = 1; |
285 | async->cb = cv; |
230 | async->cb = cv; |
286 | async->c_cb = c_cb; |
231 | async->c_cb = c_cb; |
287 | async->c_arg = c_arg; |
232 | async->c_arg = c_arg; |
288 | SvGETMAGIC (signl); |
|
|
289 | async->signum = SvOK (signl) ? sv_signum (signl) : 0; |
233 | async->signum = SvOK (signl) ? s_signum_croak (signl) : 0; |
290 | |
234 | |
291 | if (async->signum) |
235 | if (async->signum) |
292 | { |
236 | { |
293 | if (async->signum < 0) |
237 | if (async->signum < 0) |
294 | croak ("Async::Interrupt::new got passed illegal signal name or number: %s", SvPV_nolen (signl)); |
238 | croak ("Async::Interrupt::new got passed illegal signal name or number: %s", SvPV_nolen (signl)); |