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

Comparing IO-AIO/schmorp.h (file contents):
Revision 1.4 by root, Tue Jul 14 00:51:31 2009 UTC vs.
Revision 1.5 by root, Wed Jul 15 01:36:04 2009 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines