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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines