[Libevent-users] Patch for signal handling

2006-12-14 Thread David Sze
Hi,

I have an application that repeatedly forks many short-lived child
processes and waits for SIGCHLD notification.  Frequently, the
application ends up blocking in the read() call in evsignal_cb().

I think there's a condition where more than one signal is received
and evsignal_handler() is called multiple times before evsignal_cb()
gets called.  When evsignal_cb() finally runs, it drains all the
notifications from the socketpair, so the subsequent calls to
evsignal_cb() block in read().

Attached is a patch that fixes the problem in my application, but
I'm not a libevent expert so corrections would be welcome.


--- libevent-1.2a/signal.c.orig 2006-10-27 23:28:57.0 -0400
+++ libevent-1.2a/signal.c  2006-12-14 11:19:27.0 -0500
@@ -71,7 +71,7 @@
ssize_t n;
 
n = read(fd, signals, sizeof(signals));
-   if (n == -1)
+   if (n == -1  errno != EAGAIN  errno != EWOULDBLOCK)
event_err(1, %s: read, __func__);
event_add(ev, NULL);
 }
@@ -102,6 +102,7 @@
FD_CLOSEONEXEC(ev_signal_pair[1]);
 
fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
+   fcntl(ev_signal_pair[1], F_SETFL, O_NONBLOCK);
 
event_set(ev_signal, ev_signal_pair[1], EV_READ,
evsignal_cb, ev_signal);
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] [Patch] Add dns server support, ipv6 support, and misc cleanups to evdns

2006-12-14 Thread Nick Mathewson
Hi, all.  Hi, Niels!  Here's another patch to evdns.c.  This patch has
the following effects:

  - add functions for forward and reverse IPv6 lookups.
  - implement the server side of the DNS protocol: receive a set of
questions, and send an answer back to the client.
- As a subcomponent, implement the compression side of the DNS
  name compression scheme.
  - macro fix: WIN32 is sufficient; MS_WINDOWS is unnecessary.
  - suppress warnings on some compilers related to running off the end
of a function or unused variables or typechecking.
  - spelling fix: choaked-choked

The example main() function has been expanded to include demonstration
use of the server functions.  The new functions still need
documentation and references in the man page.  I've tried to test this
all as well as I could, but there may be bugs left, especially in
retrying writes after they've failed.  This patch should not introduce
bugs in code that doesn't use any of the new functions.

yrs,
-- 
Nick Mathewson
=== configure.in
==
--- configure.in(revision 11547)
+++ configure.in(local)
@@ -341,6 +341,7 @@
 AC_CHECK_TYPE(u_int32_t, unsigned int)
 AC_CHECK_TYPE(u_int16_t, unsigned short)
 AC_CHECK_TYPE(u_int8_t, unsigned char)
+AC_CHECK_TYPES(struct in6_addr, , , [#include netinet/in.h])
 
 AC_MSG_CHECKING([for socklen_t])
 AC_TRY_COMPILE([
=== evdns.c
==
--- evdns.c (revision 11547)
+++ evdns.c (local)
@@ -134,12 +134,11 @@
 #define MAX_ADDRS 4  // maximum number of addresses from a single packet
 // which we bother recording
 
-#define TYPE_A 1
-#define TYPE_CNAME 5
-#define TYPE_PTR  12
-#define TYPE_ 28
+#define TYPE_A EVDNS_TYPE_A
+#define TYPE_PTR   EVDNS_TYPE_PTR
+#define TYPE_  EVDNS_TYPE_
 
-#define CLASS_INET 1
+#define CLASS_INET EVDNS_CLASS_INET
 
 struct request {
u8 *request;  // the dns packet data
@@ -167,6 +166,12 @@
char transmit_me;  // needs to be transmitted
 };
 
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+   u8 s6_addr[16];
+};
+#endif
+
 struct reply {
unsigned int type;
unsigned int have_answer;
@@ -176,6 +181,10 @@
u32 addresses[MAX_ADDRS];
} a;
struct {
+   u32 addrcount;
+   struct in6_addr addresses[MAX_ADDRS];
+   } ;
+   struct {
char name[HOST_NAME_MAX];
} ptr;
} data;
@@ -193,13 +202,79 @@
 // when we next probe this server.
 // Valid if state == 0
char state;  // zero if we think that this server is down
-   char choaked;  // true if we have an EAGAIN from this server's socket
+   char choked;  // true if we have an EAGAIN from this server's socket
char write_waiting;  // true if we are waiting for EV_WRITE events
 };
 
 static struct request *req_head = NULL, *req_waiting_head = NULL;
 static struct nameserver *server_head = NULL;
 
+// Represents a local port where we're listening for DNS requests. Right now,
+// only UDP is supported.
+struct evdns_server_port {
+   int socket; // socket we use to read queries and write replies.
+   int refcnt; // reference count.
+   char choked; // Are we currently blocked from writing?
+   char closing; // Are we trying to close this port, pending writes?
+   evdns_request_callback_fn_type user_callback; // Fn to handle requests
+   void *user_data; // Opaque pointer passed to user_callback
+   struct event event; // Read/write event
+   // circular list of replies that we want to write.
+   struct server_request *pending_replies;
+};
+
+// Represents part of a reply being built. (That is, a single RR.)
+struct server_reply_item {
+   struct server_reply_item *next; // next item in sequence.
+   char *name; // name part of the RR
+   u16 type : 16; // The RR type
+   u16 class : 16; // The RR class (usually CLASS_INET)
+   u32 ttl; // The RR TTL
+   char is_name; // True iff data is a label
+   u16 datalen; // Length of data; -1 if data is a label
+   void *data; // The contents of the RR
+};
+
+// Represents a request that we've received as a DNS server, and holds
+// the components of the reply as we're constructing it.
+struct server_request {
+   // Pointers to the next and previous entries on the list of replies
+   // that we're waiting to write.  Only set if we have tried to respond
+   // and gotten EAGAIN.
+   struct server_request *next_pending;
+   struct server_request *prev_pending;
+
+   u16 trans_id; // Transaction id.
+   struct evdns_server_port *port; // Which port received this request on?
+   struct sockaddr_storage addr;