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 [email protected] http://monkey.org/mailman/listinfo/libevent-users
