So, I'd really like win32 libevent to be a first class libevent citizen. Right now, trunk doesn't even compile.
Attached is a first cut at trying to make win32 work better: the big issues are (1) win32.c still assumes that we're still using a global signalqueue rather than per-base queue as the new code implements. (The 1.3 branch "solves" this issue by just disabling the signalqueue on windows entirely) and (2) signal.c assumes that everybody has a working sigaction() function (which Windows does not). Also, I'm pretty sure you can't use read and write for windows sockets: only send and recv. This may not be as gloriously threadsafe as the current non-Windows code: this is where I'd like guidance. Remaining Win32 issues in trunk: (1) The win32 socketpair implementation in Win32-Code is all wrong. It returns a pair of linked win32 pipes. But select() only accepts sockets, so socketpair() in misc.c can't possibly work for libevent's needs. Once the present patch is in, I'll grab the fake-socketpair code from Tor, which has a compatible license, and which seems to work on win32 just fine. Also, it might make sense to expose this as event_socketpair() or something similar, so that all the libraries using libevent that want a socketpair can have one without reinventing the rickety dubious wheel. (2) Almost none of the files test compile under win32; in fact, they seem to be disabled. I've make some progress here, but so many of them require a working socketpair() that I'm going to hold off until the above issues are solved. Thoughts? -- Nick Mathewson
Index: configure.in =================================================================== --- configure.in (revision 440) +++ configure.in (working copy) @@ -42,7 +42,7 @@ dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h) +AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h netdb.h) if test "x$ac_cv_header_sys_queue_h" = "xyes"; then AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h) AC_EGREP_CPP(yes, @@ -135,7 +135,7 @@ AC_HEADER_TIME dnl Checks for library functions. -AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop) +AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction) if test "x$ac_cv_func_clock_gettime" = "xyes"; then AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc]) @@ -333,6 +333,9 @@ AC_LIBOBJ(evport) needsignal=yes fi +if test "x$bwin32" = "xtrue"; then + needsignal=yes +fi if test "x$needsignal" = "xyes" ; then AC_LIBOBJ(signal) fi Index: signal.c =================================================================== --- signal.c (revision 440) +++ signal.c (working copy) @@ -30,6 +30,12 @@ #include "config.h" #endif +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winsock2.h> +#undef WIN32_LEAN_AND_MEAN +#endif #include <sys/types.h> #include <sys/tree.h> #ifdef HAVE_SYS_TIME_H @@ -38,7 +44,9 @@ #include <sys/_time.h> #endif #include <sys/queue.h> +#ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> +#endif #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -67,7 +75,7 @@ struct event *ev = arg; ssize_t n; - n = read(fd, signals, sizeof(signals)); + n = recv(fd, signals, sizeof(signals), 0); if (n == -1) event_err(1, "%s: read", __func__); event_add(ev, NULL); @@ -98,7 +106,14 @@ base->sig.evsignal_caught = 0; memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); +#ifdef WIN32 + { + u_long nonblocking = 1; + ioctlsocket(base->sig.ev_signal_pair[0], FIONBIO, &nonblocking); + } +#else fcntl(base->sig.ev_signal_pair[0], F_SETFL, O_NONBLOCK); +#endif event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ, evsignal_cb, &base->sig.ev_signal); @@ -110,13 +125,16 @@ evsignal_add(struct event *ev) { int evsignal; +#ifdef HAVE_SIGACTION struct sigaction sa; +#endif struct event_base *base = ev->ev_base; if (ev->ev_events & (EV_READ|EV_WRITE)) event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); evsignal = EVENT_SIGNAL(ev); +#ifdef HAVE_SIGACTION memset(&sa, 0, sizeof(sa)); sa.sa_handler = evsignal_handler; sigfillset(&sa.sa_mask); @@ -126,6 +144,11 @@ if (sigaction(evsignal, &sa, NULL) == -1) return (-1); +#else + evsignal_base = base; + if (signal(evsignal, evsignal_handler) == SIG_ERR) + return (-1); +#endif if (!base->sig.ev_signal_added) { base->sig.ev_signal_added = 1; @@ -138,7 +161,11 @@ int evsignal_del(struct event *ev) { +#ifdef HAVE_SIGACTION return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL)); +#else + return (signal(EVENT_SIGNAL(ev),SIG_DFL))==SIG_ERR ? -1 : 0; +#endif } static void @@ -156,8 +183,13 @@ evsignal_base->sig.evsigcaught[sig]++; evsignal_base->sig.evsignal_caught = 1; +#ifndef HAVE_SIGACTION + signal(sig, evsignal_handler); +#endif + + /* Wake up our notification mechanism */ - write(evsignal_base->sig.ev_signal_pair[0], "a", 1); + send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0); errno = save_errno; } Index: WIN32-Code/win32.c =================================================================== --- WIN32-Code/win32.c (revision 440) +++ WIN32-Code/win32.c (working copy) @@ -52,7 +52,9 @@ extern struct event_list timequeue; extern struct event_list addqueue; +#if 0 extern struct event_list signalqueue; +#endif struct win_fd_set { u_int fd_count; @@ -64,10 +66,12 @@ /* MSDN says this is required to handle SIGFPE */ volatile double SIGFPE_REQ = 0.0f; +#if 0 static void signal_handler(int sig); void signal_process(void); int signal_recalc(void); +#endif struct win32op { int fd_setsz; @@ -193,6 +197,8 @@ winop->readset_out->fd_count = winop->writeset_out->fd_count = winop->exset_out->fd_count = 0; + evsignal_init(_base); + return (winop); err: XFREE(winop->readset_in); @@ -208,7 +214,10 @@ int win32_recalc(struct event_base *base, void *arg, int max) { - return (signal_recalc()); +#if 0 + return (evsignal_recalc()); +#endif + return (0); } int @@ -218,13 +227,7 @@ int i; if (ev->ev_events & EV_SIGNAL) { - if (ev->ev_events & (EV_READ|EV_WRITE)) - event_errx(1, "%s: EV_SIGNAL incompatible use", - __func__); - if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1) - return (-1); - - return (0); + return (evsignal_add(ev)); } if (!(ev->ev_events & (EV_READ|EV_WRITE))) return (0); @@ -265,7 +268,7 @@ int i, found; if (ev->ev_events & EV_SIGNAL) - return ((int)signal(EVENT_SIGNAL(ev), SIG_IGN)); + return (evsignal_del(ev)); found = -1; for (i=0;i<win32op->n_events;++i) { @@ -330,7 +333,7 @@ if (!fd_count) { /* Windows doesn't like you to call select() with no sockets */ Sleep(timeval_to_ms(tv)); - signal_process(); + evsignal_process(base); return (0); } @@ -342,8 +345,10 @@ event_debug(("%s: select returned %d", __func__, res)); if(res <= 0) { - signal_process(); + evsignal_process(base); return res; + } else if (base->sig.evsignal_caught) { + evsignal_process(base); } for (i=0;i<win32op->n_events;++i) { @@ -369,8 +374,10 @@ event_active(ev,got,1); } +#if 0 if (signal_recalc() == -1) return (-1); +#endif return (0); } @@ -380,6 +387,7 @@ { struct win32op *win32op = arg; + evsignal_dealloc(_base); if (win32op->readset_in) free(win32op->readset_in); if (win32op->writeset_in) @@ -397,6 +405,7 @@ free(win32op); } +#if 0 static void signal_handler(int sig) { @@ -435,3 +444,5 @@ memset(evsigcaught, 0, sizeof(evsigcaught)); signal_caught = 0; } +#endif +
pgpFrwwRUgR1i.pgp
Description: PGP signature
_______________________________________________ Libevent-users mailing list Libevent-users@monkey.org http://monkey.org/mailman/listinfo/libevent-users