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

Comparing EV/schmorp.h (file contents):
Revision 1.2 by root, Tue Jul 14 02:33:55 2009 UTC vs.
Revision 1.4 by root, Wed Jul 15 16:58:53 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
187 S_GENSUB_ARG = arg; 193 S_GENSUB_ARG = arg;
188 194
189 return newRV_noinc ((SV *)cv); 195 return newRV_noinc ((SV *)cv);
190} 196}
191 197
198/*****************************************************************************/
199/* portable pipe/socketpair */
200
201#ifdef USE_SOCKETS_AS_HANDLES
202# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
203#else
204# define S_TO_HANDLE(x) ((HANDLE)x)
205#endif
206
207#ifdef _WIN32
208/* taken almost verbatim from libev's ev_win32.c */
209/* oh, the humanity! */
210static int
211s_pipe (int filedes [2])
212{
213 struct sockaddr_in addr = { 0 };
214 int addr_size = sizeof (addr);
215 struct sockaddr_in adr2;
216 int adr2_size = sizeof (adr2);
217 SOCKET listener;
218 SOCKET sock [2] = { -1, -1 };
219
220 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
221 return -1;
222
223 addr.sin_family = AF_INET;
224 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
225 addr.sin_port = 0;
226
227 if (bind (listener, (struct sockaddr *)&addr, addr_size))
228 goto fail;
229
230 if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
231 goto fail;
232
233 if (listen (listener, 1))
234 goto fail;
235
236 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
237 goto fail;
238
239 if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
240 goto fail;
241
242 if ((sock [1] = accept (listener, 0, 0)) < 0)
243 goto fail;
244
245 /* windows vista returns fantasy port numbers for getpeername.
246 * example for two interconnected tcp sockets:
247 *
248 * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
249 * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
250 * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
251 * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
252 *
253 * wow! tridirectional sockets!
254 *
255 * this way of checking ports seems to work:
256 */
257 if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
258 goto fail;
259
260 if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
261 goto fail;
262
263 errno = WSAEINVAL;
264 if (addr_size != adr2_size
265 || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
266 || addr.sin_port != adr2.sin_port)
267 goto fail;
268
269 closesocket (listener);
270
271#ifdef USE_SOCKETS_AS_HANDLES
272 /* when select isn't winsocket, we also expect socket, connect, accept etc.
273 * to work on fds */
274 filedes [0] = sock [0];
275 filedes [1] = sock [1];
276#else
277 filedes [0] = _open_osfhandle (sock [0], 0);
278 filedes [1] = _open_osfhandle (sock [1], 0);
279#endif
280
281 return 0;
282
283fail:
284 closesocket (listener);
285
286 if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
287 if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
288
289 return -1;
290}
291
292#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
293
294static int
295s_fd_blocking (int fd, int blocking)
296{
297 u_long nonblocking = !blocking;
298
299 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
300}
301
302#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
303
304#else
305
306#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
307#define s_pipe(filedes) pipe (filedes)
308
309static int
310s_fd_blocking (int fd, int blocking)
311{
312 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
313}
314
315static int
316s_fd_prepare (int fd)
317{
318 return s_fd_blocking (fd, 0)
319 || fcntl (fd, F_SETFD, FD_CLOEXEC);
320}
321
322#endif
323
324#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
325/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
326# include <stdint.h>
327# ifdef __cplusplus
328extern "C" {
192#endif 329# endif
330 int eventfd (unsigned int initval, int flags);
331# ifdef __cplusplus
332}
333# endif
334#else
335# define eventfd(initval,flags) -1
336#endif
193 337
338typedef struct {
339 int fd[2]; /* read, write fd, might be equal */
340 int len; /* write length (1 pipe/socket, 8 eventfd) */
341 volatile sig_atomic_t sent;
342} s_epipe;
343
344static int
345s_epipe_new (s_epipe *epp)
346{
347 s_epipe ep;
348
349 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
350
351 if (ep.fd [0] >= 0)
352 {
353 s_fd_prepare (ep.fd [0]);
354 ep.len = 8;
355 }
356 else
357 {
358 if (s_pipe (ep.fd))
359 return -1;
360
361 if (s_fd_prepare (ep.fd [0])
362 || s_fd_prepare (ep.fd [1]))
363 {
364 close (ep.fd [0]);
365 close (ep.fd [1]);
366 return -1;
367 }
368
369 ep.len = 1;
370 }
371
372 ep.sent = 0;
373 *epp = ep;
374 return 0;
375}
376
377static void
378s_epipe_destroy (s_epipe *epp)
379{
380 close (epp->fd [0]);
381
382 if (epp->fd [1] != epp->fd [0])
383 close (epp->fd [1]);
384
385 epp->len = 0;
386}
387
388static void
389s_epipe_signal (s_epipe *epp)
390{
391 if (epp->sent)
392 return;
393
394 epp->sent = 1;
395 {
396#ifdef _WIN32
397 /* perl overrides send with a function that crashes in other threads.
398 * unfortunately, it overrides it with an argument-less macro, so
399 * there is no way to force usage of the real send function.
400 * incompetent windows programmers - is this redundant?
401 */
402 DWORD dummy;
403 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
404#else
405 static uint64_t counter = 1;
406 write (epp->fd [1], &counter, epp->len);
407#endif
408 }
409}
410
411static void
412s_epipe_drain (s_epipe *epp)
413{
414 char buf [9];
415
416#ifdef _WIN32
417 recv (epp->fd [0], buf, sizeof (buf), 0);
418#else
419 read (epp->fd [0], buf, sizeof (buf));
420#endif
421
422 epp->sent = 0;
423}
424
425/* like new, but dups over old */
426static int
427s_epipe_renew (s_epipe *epp)
428{
429 s_epipe epn;
430
431 if (epp->fd [1] != epp->fd [0])
432 close (epp->fd [1]);
433
434 if (s_epipe_new (&epn))
435 return -1;
436
437 if (epp->len)
438 {
439 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
440 croak ("unable to dup over old event pipe"); /* should not croak */
441
442 if (epp->fd [1] != epp->fd [0])
443 close (epn.fd [0]);
444
445 epn.fd [0] = epp->fd [0];
446 }
447
448 *epp = epn;
449
450 return 0;
451}
452
453#define s_epipe_fd(epp) ((epp)->fd [0])
454
455static int
456s_epipe_wait (s_epipe *epp)
457{
458#ifdef _WIN32
459 fd_set rfd;
460 int fd = s_epipe_fd (epp);
461
462 FD_ZERO (&rfd);
463 FD_SET (fd, &rfd);
464
465 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
466#else
467 /* poll is preferable on posix systems */
468 struct pollfd pfd;
469
470 pfd.fd = s_epipe_fd (epp);
471 pfd.events = POLLIN;
472
473 return poll (&pfd, 1, 0);
474#endif
475}
476
477#endif
478

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines