ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/schmorp.h
(Generate patch)

Comparing EV/schmorp.h (file contents):
Revision 1.1 by root, Tue Jul 14 00:09:59 2009 UTC vs.
Revision 1.7 by root, Sun Aug 9 13:30:41 2009 UTC

1#ifndef SCHMORP_PERL_H_ 1#ifndef SCHMORP_PERL_H_
2#define SCHMORP_PERL_H_ 2#define SCHMORP_PERL_H_
3 3
4/* WARNING
5 * This header file is a shared resource between many modules.
6 */
7
8#include <signal.h>
9#include <errno.h>
10
11#ifndef _WIN32
12# include <poll.h>
13#endif
14
4/* useful stuff, used by schmorp mostly */ 15/* useful stuff, used by schmorp mostly */
16
17#include "patchlevel.h"
5 18
6#define PERL_VERSION_ATLEAST(a,b,c) \ 19#define PERL_VERSION_ATLEAST(a,b,c) \
7 (PERL_REVISION > (a) \ 20 (PERL_REVISION > (a) \
8 || (PERL_REVISION == (a) \ 21 || (PERL_REVISION == (a) \
9 && (PERL_VERSION > (b) \ 22 && (PERL_VERSION > (b) \
10 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c))))) 23 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
11 24
25#ifndef PERL_MAGIC_ext
26# define PERL_MAGIC_ext '~'
27#endif
28
12#if !PERL_VERSION_ATLEAST (5,6,0) 29#if !PERL_VERSION_ATLEAST (5,6,0)
13# ifndef PL_ppaddr 30# ifndef PL_ppaddr
14# define PL_ppaddr ppaddr 31# define PL_ppaddr ppaddr
15# endif 32# endif
16# ifndef call_sv 33# ifndef call_sv
68#ifndef SIG_SIZE 85#ifndef SIG_SIZE
69 /* kudos to Slaven Rezic for the idea */ 86 /* kudos to Slaven Rezic for the idea */
70 static char sig_size [] = { SIG_NUM }; 87 static char sig_size [] = { SIG_NUM };
71# define SIG_SIZE (sizeof (sig_size) + 1) 88# define SIG_SIZE (sizeof (sig_size) + 1)
72#endif 89#endif
90 dTHX;
73 int signum; 91 int signum;
74 92
75 SvGETMAGIC (sig); 93 SvGETMAGIC (sig);
76 94
77 for (signum = 1; signum < SIG_SIZE; ++signum) 95 for (signum = 1; signum < SIG_SIZE; ++signum)
90s_signum_croak (SV *sig) 108s_signum_croak (SV *sig)
91{ 109{
92 int signum = s_signum (sig); 110 int signum = s_signum (sig);
93 111
94 if (signum < 0) 112 if (signum < 0)
113 {
114 dTHX;
95 croak ("%s: invalid signal name or number", SvPV_nolen (sig)); 115 croak ("%s: invalid signal name or number", SvPV_nolen (sig));
116 }
96 117
97 return signum; 118 return signum;
98} 119}
99 120
100static int 121static int
101s_fileno (SV *fh, int wr) 122s_fileno (SV *fh, int wr)
102{ 123{
124 dTHX;
103 SvGETMAGIC (fh); 125 SvGETMAGIC (fh);
104 126
105 if (SvROK (fh)) 127 if (SvROK (fh))
106 { 128 {
107 fh = SvRV (fh); 129 fh = SvRV (fh);
121s_fileno_croak (SV *fh, int wr) 143s_fileno_croak (SV *fh, int wr)
122{ 144{
123 int fd = s_fileno (fh, wr); 145 int fd = s_fileno (fh, wr);
124 146
125 if (fd < 0) 147 if (fd < 0)
148 {
149 dTHX;
126 croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh)); 150 croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh));
151 }
127 152
128 return fd; 153 return fd;
129} 154}
130 155
131static SV * 156static SV *
132s_get_cv (SV *cb_sv) 157s_get_cv (SV *cb_sv)
133{ 158{
159 dTHX;
134 HV *st; 160 HV *st;
135 GV *gvp; 161 GV *gvp;
162
136 CV *cv = sv_2cv (cb_sv, &st, &gvp, 0); 163 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
137
138 return (SV *)cv;
139} 164}
140 165
141static SV * 166static SV *
142s_get_cv_croak (SV *cb_sv) 167s_get_cv_croak (SV *cb_sv)
143{ 168{
144 cb_sv = s_get_cv (cb_sv); 169 SV *cv = s_get_cv (cb_sv);
145 170
146 if (!cb_sv) 171 if (!cv)
172 {
173 dTHX;
147 croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv)); 174 croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv));
175 }
148 176
149 return cb_sv; 177 return cv;
150} 178}
151 179
152/*****************************************************************************/ 180/*****************************************************************************/
153/* gensub: simple closure generation utility */ 181/* gensub: simple closure generation utility */
154 182
170 S_GENSUB_ARG = arg; 198 S_GENSUB_ARG = arg;
171 199
172 return newRV_noinc ((SV *)cv); 200 return newRV_noinc ((SV *)cv);
173} 201}
174 202
203/*****************************************************************************/
204/* portable pipe/socketpair */
205
206#ifdef USE_SOCKETS_AS_HANDLES
207# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
208#else
209# define S_TO_HANDLE(x) ((HANDLE)x)
210#endif
211
212#ifdef _WIN32
213/* taken almost verbatim from libev's ev_win32.c */
214/* oh, the humanity! */
215static int
216s_pipe (int filedes [2])
217{
218 dTHX;
219
220 struct sockaddr_in addr = { 0 };
221 int addr_size = sizeof (addr);
222 struct sockaddr_in adr2;
223 int adr2_size = sizeof (adr2);
224 SOCKET listener;
225 SOCKET sock [2] = { -1, -1 };
226
227 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
228 return -1;
229
230 addr.sin_family = AF_INET;
231 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
232 addr.sin_port = 0;
233
234 if (bind (listener, (struct sockaddr *)&addr, addr_size))
235 goto fail;
236
237 if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
238 goto fail;
239
240 if (listen (listener, 1))
241 goto fail;
242
243 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
244 goto fail;
245
246 if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
247 goto fail;
248
249 if ((sock [1] = accept (listener, 0, 0)) < 0)
250 goto fail;
251
252 /* windows vista returns fantasy port numbers for getpeername.
253 * example for two interconnected tcp sockets:
254 *
255 * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
256 * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
257 * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
258 * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
259 *
260 * wow! tridirectional sockets!
261 *
262 * this way of checking ports seems to work:
263 */
264 if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
265 goto fail;
266
267 if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
268 goto fail;
269
270 errno = WSAEINVAL;
271 if (addr_size != adr2_size
272 || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
273 || addr.sin_port != adr2.sin_port)
274 goto fail;
275
276 closesocket (listener);
277
278#ifdef USE_SOCKETS_AS_HANDLES
279 /* when select isn't winsocket, we also expect socket, connect, accept etc.
280 * to work on fds */
281 filedes [0] = sock [0];
282 filedes [1] = sock [1];
283#else
284 filedes [0] = _open_osfhandle (sock [0], 0);
285 filedes [1] = _open_osfhandle (sock [1], 0);
286#endif
287
288 return 0;
289
290fail:
291 closesocket (listener);
292
293 if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
294 if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
295
296 return -1;
297}
298
299#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
300
301static int
302s_fd_blocking (int fd, int blocking)
303{
304 u_long nonblocking = !blocking;
305
306 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
307}
308
309#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
310
311#else
312
313#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
314#define s_pipe(filedes) pipe (filedes)
315
316static int
317s_fd_blocking (int fd, int blocking)
318{
319 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
320}
321
322static int
323s_fd_prepare (int fd)
324{
325 return s_fd_blocking (fd, 0)
326 || fcntl (fd, F_SETFD, FD_CLOEXEC);
327}
328
329#endif
330
331#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
332/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
333# include <stdint.h>
334# ifdef __cplusplus
335extern "C" {
175#endif 336# endif
337 int eventfd (unsigned int initval, int flags);
338# ifdef __cplusplus
339}
340# endif
341#else
342# define eventfd(initval,flags) -1
343#endif
176 344
345typedef struct {
346 int fd[2]; /* read, write fd, might be equal */
347 int len; /* write length (1 pipe/socket, 8 eventfd) */
348} s_epipe;
349
350static int
351s_epipe_new (s_epipe *epp)
352{
353 s_epipe ep;
354
355 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
356
357 if (ep.fd [0] >= 0)
358 {
359 s_fd_prepare (ep.fd [0]);
360 ep.len = 8;
361 }
362 else
363 {
364 if (s_pipe (ep.fd))
365 return -1;
366
367 if (s_fd_prepare (ep.fd [0])
368 || s_fd_prepare (ep.fd [1]))
369 {
370 dTHX;
371
372 close (ep.fd [0]);
373 close (ep.fd [1]);
374 return -1;
375 }
376
377 ep.len = 1;
378 }
379
380 *epp = ep;
381 return 0;
382}
383
384static void
385s_epipe_destroy (s_epipe *epp)
386{
387 dTHX;
388
389 close (epp->fd [0]);
390
391 if (epp->fd [1] != epp->fd [0])
392 close (epp->fd [1]);
393
394 epp->len = 0;
395}
396
397static void
398s_epipe_signal (s_epipe *epp)
399{
400#ifdef _WIN32
401 /* perl overrides send with a function that crashes in other threads.
402 * unfortunately, it overrides it with an argument-less macro, so
403 * there is no way to force usage of the real send function.
404 * incompetent windows programmers - is this redundant?
405 */
406 DWORD dummy;
407 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
408#else
409 static uint64_t counter = 1;
410 /* some modules accept fd's from outside, support eventfd here */
411 if (write (epp->fd [1], &counter, epp->len) < 0
412 && errno == EINVAL
413 && epp->len != 8)
414 write (epp->fd [1], &counter, (epp->len = 8));
415#endif
416}
417
418static void
419s_epipe_drain (s_epipe *epp)
420{
421 dTHX;
422 char buf [9];
423
424#ifdef _WIN32
425 recv (epp->fd [0], buf, sizeof (buf), 0);
426#else
427 read (epp->fd [0], buf, sizeof (buf));
428#endif
429}
430
431/* like new, but dups over old */
432static int
433s_epipe_renew (s_epipe *epp)
434{
435 dTHX;
436 s_epipe epn;
437
438 if (epp->fd [1] != epp->fd [0])
439 close (epp->fd [1]);
440
441 if (s_epipe_new (&epn))
442 return -1;
443
444 if (epp->len)
445 {
446 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
447 croak ("unable to dup over old event pipe"); /* should not croak */
448
449 if (epp->fd [1] != epp->fd [0])
450 close (epn.fd [0]);
451
452 epn.fd [0] = epp->fd [0];
453 }
454
455 *epp = epn;
456
457 return 0;
458}
459
460#define s_epipe_fd(epp) ((epp)->fd [0])
461
462static int
463s_epipe_wait (s_epipe *epp)
464{
465 dTHX;
466#ifdef _WIN32
467 fd_set rfd;
468 int fd = s_epipe_fd (epp);
469
470 FD_ZERO (&rfd);
471 FD_SET (fd, &rfd);
472
473 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
474#else
475 /* poll is preferable on posix systems */
476 struct pollfd pfd;
477
478 pfd.fd = s_epipe_fd (epp);
479 pfd.events = POLLIN;
480
481 return poll (&pfd, 1, -1);
482#endif
483}
484
485#endif
486

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines