signals via pipes.
svn:r105
/* #undef u_int8_t */
/* Define if timeradd is defined in <sys/time.h> */
-#define HAVE_TIMERADD 1
+/* #undef HAVE_TIMERADD */
#ifndef HAVE_TIMERADD
#define timeradd(tvp, uvp, vvp) \
do { \
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
+/* #undef HAVE_SYS_TIME_H */
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+/* #undef HAVE_UNISTD_H */
/* Define to 1 if you have the `warnx' function. */
#define HAVE_WARNX 1
/* Version number of package */
#define VERSION "0.6"
+
+typedef unsigned char u_char;
+
+/* Winsock compatibility */
+#define SHUT_WR SD_SEND
+
+struct timeval;
+struct timezone;
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+
+#define read win_read
+#define write win_write
+
+int win_read(int, void *, unsigned int);
+int win_write(int, void *, unsigned int);
+int socketpair(int d, int type, int protocol, int *sv);
+
+#define __func__ __FILE__
\ No newline at end of file
tv->tv_usec = ((int) tb.millitm) * 1000;
return 0;
}
+
+int
+win_read(int fd, void *buf, unsigned int length)
+{
+ DWORD dwBytesRead;
+ int res = ReadFile((HANDLE) fd, buf, length, &dwBytesRead, NULL);
+ if (res == 0) {
+ DWORD error = GetLastError();
+ if (error == ERROR_NO_DATA)
+ return (0);
+ return (-1);
+ } else
+ return (dwBytesRead);
+}
+
+int
+win_write(int fd, void *buf, unsigned int length)
+{
+ DWORD dwBytesWritten;
+ int res = WriteFile((HANDLE) fd, buf, length, &dwBytesWritten, NULL);
+ if (res == 0) {
+ DWORD error = GetLastError();
+ if (error == ERROR_NO_DATA)
+ return (0);
+ return (-1);
+ } else
+ return (dwBytesWritten);
+}
+
+int
+socketpair(int d, int type, int protocol, int *sv)
+{
+ static int count;
+ char buf[64];
+ HANDLE fd;
+ DWORD dwMode;
+ sprintf(buf, "\\\\.\\pipe\\levent-%d", count++);
+ /* Create a duplex pipe which will behave like a socket pair */
+ fd = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT,
+ PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
+ if (fd == INVALID_HANDLE_VALUE)
+ return (-1);
+ sv[0] = (int)fd;
+
+ fd = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fd == INVALID_HANDLE_VALUE)
+ return (-1);
+ dwMode = PIPE_NOWAIT;
+ SetNamedPipeHandleState(fd, &dwMode, NULL, NULL);
+ sv[1] = (int)fd;
+
+ return (0);
+}
\ No newline at end of file
void
evbuffer_free(struct evbuffer *buffer)
{
- if (buffer->buffer != NULL)
- free(buffer->buffer);
+ if (buffer->orig_buffer != NULL)
+ free(buffer->orig_buffer);
free(buffer);
}
* the other buffer.
*/
+#define SWAP(x,y) do { \
+ (x)->buffer = (y)->buffer; \
+ (x)->orig_buffer = (y)->orig_buffer; \
+ (x)->misalign = (y)->misalign; \
+ (x)->totallen = (y)->totallen; \
+ (x)->off = (y)->off; \
+} while (0)
+
int
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
{
int res;
+
+ /* Short cut for better performance */
+ if (outbuf->off == 0) {
+ struct evbuffer tmp;
+ size_t oldoff = inbuf->off;
+
+ /* Swap them directly */
+ SWAP(&tmp, outbuf);
+ SWAP(outbuf, inbuf);
+ SWAP(inbuf, &tmp);
+
+ /*
+ * Optimization comes with a price; we need to notify the
+ * buffer if necessary of the changes. oldoff is the amount
+ * of data that we tranfered from inbuf to outbuf
+ */
+ if (inbuf->off != oldoff && inbuf->cb != NULL)
+ (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
+ if (oldoff && outbuf->cb != NULL)
+ (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
+
+ return (0);
+ }
+
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
if (res == 0)
evbuffer_drain(inbuf, inbuf->off);
{
int res = -1;
char *msg;
+#ifdef WIN32
+ static char buffer[4096];
+#endif
va_list ap;
va_start(ap, fmt);
+#ifndef WIN32
if (vasprintf(&msg, fmt, ap) == -1)
goto end;
+#else
+ _vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
+ buffer[sizeof(buffer)-1] = '\0';
+ msg = buffer;
+#endif
res = strlen(msg);
if (evbuffer_add(buf, msg, res) == -1)
res = -1;
+#ifndef WIN32
free(msg);
- end:
+end:
+#endif
va_end(ap);
return (res);
}
+/* Reads data from an event buffer and drains the bytes read */
+
int
-evbuffer_add(struct evbuffer *buf, u_char *data, size_t datlen)
+evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
{
- size_t need = buf->off + datlen;
- size_t oldoff = buf->off;
+ int nread = datlen;
+ if (nread >= buf->off)
+ nread = buf->off;
- if (buf->totallen < need) {
- void *newbuf;
- int length = buf->totallen;
+ memcpy(data, buf->buffer, nread);
+ evbuffer_drain(buf, nread);
+
+ return (nread);
+}
+
+/* Adds data to an event buffer */
- if (length < 256)
- length = 256;
- while (length < need)
- length <<= 1;
+static __inline void
+evbuffer_align(struct evbuffer *buf)
+{
+ memmove(buf->orig_buffer, buf->buffer, buf->off);
+ buf->buffer = buf->orig_buffer;
+ buf->misalign = 0;
+}
- if ((newbuf = realloc(buf->buffer, length)) == NULL)
- return (-1);
+int
+evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
+{
+ size_t need = buf->misalign + buf->off + datlen;
+ size_t oldoff = buf->off;
- buf->buffer = newbuf;
- buf->totallen = length;
+ if (buf->totallen < need) {
+ if (buf->misalign >= datlen) {
+ evbuffer_align(buf);
+ } else {
+ void *newbuf;
+ size_t length = buf->totallen;
+
+ if (length < 256)
+ length = 256;
+ while (length < need)
+ length <<= 1;
+
+ if (buf->orig_buffer != buf->buffer)
+ evbuffer_align(buf);
+ if ((newbuf = realloc(buf->buffer, length)) == NULL)
+ return (-1);
+
+ buf->orig_buffer = buf->buffer = newbuf;
+ buf->totallen = length;
+ }
}
memcpy(buf->buffer + buf->off, data, datlen);
if (len >= buf->off) {
buf->off = 0;
+ buf->buffer = buf->orig_buffer;
+ buf->misalign = 0;
goto done;
}
- memmove(buf->buffer, buf->buffer + len, buf->off - len);
+ buf->buffer += len;
+ buf->misalign += len;
+
buf->off -= len;
done:
{
u_char inbuf[4096];
int n;
+#ifdef WIN32
+ DWORD dwBytesRead;
+#endif
if (howmuch < 0 || howmuch > sizeof(inbuf))
howmuch = sizeof(inbuf);
+#ifndef WIN32
n = read(fd, inbuf, howmuch);
if (n == -1)
return (-1);
if (n == 0)
return (0);
+#else
+ n = ReadFile((HANDLE)fd, inbuf, howmuch, &dwBytesRead, NULL);
+ if (n == 0)
+ return (-1);
+ if (dwBytesRead == 0)
+ return (0);
+ n = dwBytesRead;
+#endif
evbuffer_add(buffer, inbuf, n);
evbuffer_write(struct evbuffer *buffer, int fd)
{
int n;
+#ifdef WIN32
+ DWORD dwBytesWritten;
+#endif
+#ifndef WIN32
n = write(fd, buffer->buffer, buffer->off);
if (n == -1)
return (-1);
if (n == 0)
return (0);
-
+#else
+ n = WriteFile((HANDLE)fd, buffer->buffer, buffer->off, &dwBytesWritten, NULL);
+ if (n == 0)
+ return (-1);
+ if (dwBytesWritten == 0)
+ return (0);
+ n = dwBytesWritten;
+#endif
evbuffer_drain(buffer, n);
return (n);
NULL
};
+/* Global state */
+
const struct eventop *evsel;
void *evbase;
+static int event_count;
/* Handle signals - This is a deprecated interface */
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
return (1);
if (a < b)
return (-1);
- if (a > b)
+ else if (a > b)
return (1);
return (0);
}
event_gotsig = 0;
gettimeofday(&event_tv, NULL);
+#if defined(USE_LOG) && defined(USE_DEBUG)
+ log_to(stderr);
+ log_debug_cmd(LOG_MISC, 80);
+#endif
+
RB_INIT(&timetree);
TAILQ_INIT(&eventqueue);
TAILQ_INIT(&activequeue);
if (getenv("EVENT_SHOW_METHOD"))
fprintf(stderr, "libevent using: %s\n", evsel->name);
-
-#if defined(USE_LOG) && defined(USE_DEBUG)
- log_to(stderr);
- log_debug_cmd(LOG_MISC, 80);
-#endif
}
int
event_haveevents(void)
{
- return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
- TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
+ return (event_count > 0);
}
static void
errx(1, "%s: %p(fd %d) not on queue %x", __func__,
ev, ev->ev_fd, queue);
+ if (!(ev->ev_flags & EVLIST_INTERNAL))
+ event_count--;
+
ev->ev_flags &= ~queue;
switch (queue) {
case EVLIST_ACTIVE:
errx(1, "%s: %p(fd %d) already on queue %x", __func__,
ev, ev->ev_fd, queue);
+ if (!(ev->ev_flags & EVLIST_INTERNAL))
+ event_count++;
+
ev->ev_flags |= queue;
switch (queue) {
case EVLIST_ACTIVE:
#define EVLIST_INSERTED 0x02
#define EVLIST_SIGNAL 0x04
#define EVLIST_ACTIVE 0x08
+#define EVLIST_INTERNAL 0x10
#define EVLIST_INIT 0x80
/* EVLIST_X_ Private space: 0x1000-0xf000 */
-#define EVLIST_ALL (0xf000 | 0x8f)
+#define EVLIST_ALL (0xf000 | 0x9f)
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
struct evbuffer {
u_char *buffer;
+ u_char *orig_buffer;
+ size_t misalign;
size_t totallen;
size_t off;
struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *);
-int evbuffer_add(struct evbuffer *, u_char *, size_t);
+int evbuffer_add(struct evbuffer *, void *, size_t);
+int evbuffer_remove(struct evbuffer *, void *, size_t);
int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
void evbuffer_drain(struct evbuffer *, size_t);
return;
}
- buf[dwBytesRead + 1] = '\0';
+ buf[dwBytesRead] = '\0';
#else
len = read(fd, buf, sizeof(buf) - 1);
*/
#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <sys/stat.h>
#ifndef WIN32
#include <sys/queue.h>
*/
#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <sys/stat.h>
#ifndef WIN32
#include <sys/queue.h>
#else
#include <time.h>
#endif
+#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/_time.h>
#endif
#include <sys/queue.h>
+#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int evsignal_recalc(sigset_t *);
int evsignal_deliver(sigset_t *);
+static struct event ev_signal;
+static int ev_signal_pair[2];
+static int ev_signal_added;
+
+/* Callback for when the signal handler write a byte to our signaling socket */
+static void evsignal_cb(int fd, short what, void *arg)
+{
+ static char signals[100];
+ struct event *ev = arg;
+ int n;
+
+ n = read(fd, signals, sizeof(signals));
+ if (n == -1)
+ err(1, "%s: read");
+ event_add(ev, NULL);
+}
+
void
evsignal_init(sigset_t *evsigmask)
{
sigemptyset(evsigmask);
+
+ /*
+ * Our signal handler is going to write to one end of the socket
+ * pair to wake up our event loop. The event loop then scans for
+ * signals that got delivered.
+ */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
+ err(1, "%s: socketpair", __func__);
+
+ event_set(&ev_signal, ev_signal_pair[1], EV_READ,
+ evsignal_cb, &ev_signal);
+ ev_signal.ev_flags |= EVLIST_INTERNAL;
}
int
{
evsigcaught[sig]++;
evsignal_caught = 1;
+
+ /* Wake up our notification mechanism */
+ write(ev_signal_pair[0], "a", 1);
}
int
{
struct sigaction sa;
struct event *ev;
+
+ if (!ev_signal_added) {
+ ev_signal_added = 1;
+ event_add(&ev_signal, NULL);
+ }
if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc)
return (0);
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
+#ifndef WIN32
#include <sys/socket.h>
#include <sys/signal.h>
+#include <unistd.h>
+#endif
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <unistd.h>
#include <errno.h>
#include <event.h>
int
cleanup_test(void)
{
+#ifndef WIN32
close(pair[0]);
close(pair[1]);
-
+#else
+ CloseHandle((HANDLE)pair[0]);
+ CloseHandle((HANDLE)pair[1]);
+#endif
if (test_ok)
fprintf(stdout, "OK\n");
else {
cleanup_test();
}
+#ifndef WIN32
void
test7(void)
{
cleanup_test();
}
+#endif
void
test8(void)
int
main (int argc, char **argv)
{
+#ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+#endif
+
setvbuf(stdout, NULL, _IONBF, 0);
/* Initalize the event library */
test5();
test6();
-
+#ifndef WIN32
test7();
-
+#endif
test8();
test9();