File Coverage

Pipe.xs
Criterion Covered Total %
statement 38 41 92.6
total 38 41 92.6


line stmt code
1   #define PERL_NO_GET_CONTEXT
2   #include "EXTERN.h"
3   #include "perl.h"
4   #include "XSUB.h"
5    
6   static volatile sig_atomic_t handles[NSIG];
7    
8 1 static void kill_handler(int signo) {
9 1 struct sigaction action = { 0 };
10 1 sigaction(signo, &action, NULL);
11 1 close(handles[signo]);
12 1 handles[signo] = -1;
13 1 }
14    
15 1 static void handler(int signo) {
16 1 int fd = handles[signo];
17 1 if (fd >= 0 && write(fd, "\x01", 1) < 0 && errno != EAGAIN)
18 0 kill_handler(signo);
19 1 }
20    
21 2 static void nonblock(int fd) {
22 2 int base = fcntl(fd, F_GETFL, 0);
23 2 fcntl(fd, F_SETFL, base | O_NONBLOCK);
24 2 }
25    
26 1 static SV* S_io_fdopen(pTHX_ int fd, const char* classname) {
27 1 PerlIO* pio = PerlIO_fdopen(fd, "r");
28 1 GV* gv = newGVgen(classname);
29 1 SV* ret = newRV_noinc((SV*)gv);
30 1 IO* io = GvIOn(gv);
31 1 IoTYPE(io) = '<';
32 1 IoIFP(io) = pio;
33 1 IoOFP(io) = pio;
34 1 return ret;
35   }
36   #define io_fdopen(fd, classname) S_io_fdopen(aTHX_ fd, classname)
37    
38 1 static int pipe_destroy(pTHX_ SV* sv, MAGIC* magic) {
39 1 kill_handler(magic->mg_len);
40 1 }
41    
42   static const MGVTBL pipe_magic = { NULL, NULL, NULL, NULL, pipe_destroy };
43    
44   MODULE = Signal::Pipe PACKAGE = Signal::Pipe
45    
46   PROTOTYPES: DISABLED
47    
48   BOOT:
49   int i;
50 66 for (i = 0; i < NSIG; ++i)
51 65 handles[i] = -1;
52    
53   SV*
54   selfpipe(signo);
55   int signo;
56   PREINIT:
57   int fds[2];
58 1 struct sigaction action = {0};
59   CODE:
60 1 if (handles[signo] >= 0)
61 0 Perl_croak(aTHX_ "Self pipe already established for signal %d", signo);
62 1 if (pipe(fds) == -1)
63 0 Perl_croak(aTHX_ "Couldn't open a pipe: %s", Strerror(errno));
64   if (fds[1] > SIG_ATOMIC_MAX)
65   Perl_croak(aTHX_ "Pipe descriptor doesn't fit in a sig_atomic_t");
66 1 nonblock(fds[0]);
67 1 nonblock(fds[1]);
68 1 handles[signo] = fds[1];
69    
70 1 action.sa_handler = handler;
71 1 sigaction(signo, &action, NULL);
72    
73 1 RETVAL = io_fdopen(fds[0], "Signal::Pipe");
74 1 sv_magicext(SvRV(RETVAL), NULL, PERL_MAGIC_ext, &pipe_magic, NULL, signo);
75   OUTPUT:
76   RETVAL
77