From elliotf-libevent at gratuitous.net Wed Aug 1 16:36:02 2007 From: elliotf-libevent at gratuitous.net (Elliot Foster) Date: Wed Aug 1 16:36:08 2007 Subject: [Libevent-users] evhttp_dispatch_callback fix (so '/some?this=that' does not match '/something') Message-ID: <46B0EEB2.10300@gratuitous.net> Another quick fix for the dispatch callback, for when it goes through available callbacks looking for a match. The problem is that if the request URI has an argument, the comparison is done on the bytes before the url parameter separator. The result is that the lookup will result in mismatches, especially for a request URI like '/?some_arg=some_val' that will match the first callback found. Two potential fixes are attached, one that modifies the string to replace the argument separator with a null char before the strcmp, and another that checks for a null char in the potential match (at the same offset as the argument separator.) Thanks, Elliot -------------- next part -------------- A non-text attachment was scrubbed... Name: libevent-1.3c-evhttp_dispatch_callback-ver1.diff Type: text/x-patch Size: 529 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070801/7405f6b8/libevent-1.3c-evhttp_dispatch_callback-ver1.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: libevent-1.3c-evhttp_dispatch_callback-ver2.diff Type: text/x-patch Size: 783 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070801/7405f6b8/libevent-1.3c-evhttp_dispatch_callback-ver2.bin From elliotf-libevent at gratuitous.net Thu Aug 2 15:52:20 2007 From: elliotf-libevent at gratuitous.net (Elliot Foster) Date: Thu Aug 2 15:52:30 2007 Subject: [Libevent-users] evhttp_dispatch_callback fix (so '/some?this=that' does not match '/something') In-Reply-To: <46B0EEB2.10300@gratuitous.net> References: <46B0EEB2.10300@gratuitous.net> Message-ID: <46B235F4.1050603@gratuitous.net> Here's a follow-up with a regression test (attached.) Elliot Elliot Foster wrote: > Another quick fix for the dispatch callback, for when it goes through > available callbacks looking for a match. The problem is that if the > request URI has an argument, the comparison is done on the bytes before > the url parameter separator. The result is that the lookup will result > in mismatches, especially for a request URI like '/?some_arg=some_val' > that will match the first callback found. > > Two potential fixes are attached, one that modifies the string to > replace the argument separator with a null char before the strcmp, and > another that checks for a null char in the potential match (at the same > offset as the argument separator.) > > Thanks, > > Elliot > > > ------------------------------------------------------------------------ > > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users -------------- next part -------------- A non-text attachment was scrubbed... Name: libevent-1.3c-dispatch_callback-regression_test.diff Type: text/x-patch Size: 3019 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070802/cdbfec72/libevent-1.3c-dispatch_callback-regression_test.bin From mark at heily.com Fri Aug 3 20:40:38 2007 From: mark at heily.com (Mark Heily) Date: Fri Aug 3 20:40:47 2007 Subject: [Libevent-users] Re: [PATCH] libevent-doxygen.diff In-Reply-To: <850f7cbe0707302032u42238226tf577d60e23f09705@mail.gmail.com> References: <1177989356.18996.26.camel@voltaire> <850f7cbe0707302032u42238226tf577d60e23f09705@mail.gmail.com> Message-ID: <1186188038.18023.8.camel@voltaire> Hi Niels, The Doxygen patch applies cleanly to the libevent trunk as of August 3rd. If you like the idea of self-documenting code, I could redo the patch to annotate the real event.h and evdns.h, instead of creating a copy in the doxygen/ subdirectory. This makes it easier to keep the code and documentation in sync in the future; when you change the code, change the documentation with it. If the two things are kept separate, they can fall out of sync more easily. Also you may be interested in a project of mine called pnotify. It is like libevent but for filesystem events; for example, the EVFILT_VNODE events for kqueue, and the inotify(7) facility for Linux. It provides a portable way to watch for events such as file creation, modification, and deletion. The project web page is http://mark.heily.com/pnotify and it is already very functional and ported to all BSDs, MacOS, and Linux. I think it might be a good candidate for importing into the libevent tree in the same way you did with evdns. This would allow people to add callbacks for filesystem events that would be integrated with the libevent main loop. Best regards, Mark On Mon, 2007-07-30 at 20:32 -0700, Niels Provos wrote: > Hi Mark, > > I am slowly catching up on my email back log. Could you please check > if your doxygen patch still works against trunk? > > Thank you, > Niels. > > On 4/30/07, Mark Heily wrote: > > Here are the annotated header files and the Doxygen configuration file > > that can be used to generate the libevent API reference manual found at > > http://naturalc.org/libevent/. > > > > This patch creates the following files: > > > > doxygen/ > > doxygen/Doxyfile > > doxygen/event.h > > doxygen/evdns.h > > doxygen/evhttp.h > > > > It also modifies Makefile.am to include these files in the source > > tarball when running 'make dist'. > > > > After applying the patch, go to the doxygen/ subdirectory and run > > 'doxygen' to generate the documentation. > > > > Regards, > > > > - Mark > > > > P.S. For legal purposes, > > > > I, Mark Heily, hereby place the following modifications to libevent into > > the public domain. Hence, these modifications may be freely used and/or > > redistributed for any purpose with or without attribution and/or other > > notice. > > > > diff -ruN ../libevent.OLD/doxygen/Doxyfile ./doxygen/Doxyfile > > --- ../libevent.OLD/doxygen/Doxyfile 1969-12-31 19:00:00.000000000 -0500 > > +++ ./doxygen/Doxyfile 2007-04-30 23:02:31.000000000 -0400 > > @@ -0,0 +1,226 @@ > > +# Doxyfile 1.5.1 > > + > > +# This file describes the settings to be used by the documentation system > > +# doxygen (www.doxygen.org) for a project > > +# From clayne at anodized.com Sat Aug 4 22:04:29 2007 From: clayne at anodized.com (Christopher Layne) Date: Sat Aug 4 22:04:40 2007 Subject: [Libevent-users] [PATCH] initialize ev_res In-Reply-To: <469FC642.3040604@slamb.org> References: <469FC642.3040604@slamb.org> Message-ID: <20070805020429.GG17302@ns1.anodized.com> On Thu, Jul 19, 2007 at 01:14:58PM -0700, Scott Lamb wrote: > When I use "valgrind --tool=memcheck" on a libevent-based program, it > gives the following complaint: > > ==15442== Conditional jump or move depends on uninitialised value(s) > ==15442== at 0x4C0F2D3: event_add (event.c:632) > ==15442== by 0x405EE4: main_loop (net.c:356) > ==15442== by 0x411853: main (tincd.c:329) > > Here's the relevant portion of event.c: > > 632 if ((ev->ev_flags & EVLIST_ACTIVE) && > 633 (ev->ev_res & EV_TIMEOUT)) { > > I've looked through the libevent code and verified that ev_res is always > initialized when (ev_flags & EVLIST_ACTIVE) is true, so there's no real > bug here. You wouldn't happen to have a copy of the code or atleast code segment which was tickling this would you? When valgrind complains about uninitialised values, it's not in the fashion of gcc in that "this could be uninitialised - so watch out" type of noise. It really is an uninitalised area being read from. I also looked through event.c, and couldn't find a particular logic path that would cause it, nor could I get valgrind to duplicate it with simple libevent test code. Sometimes when valgrind indicates this error, I split the logic into two separate conditionals as it's not always apparent which particular object is at fault. It seems pretty obvious to me it wasn't ev_flags, as that was explicitly initialised, leaving only ev_res - but as I said I couldn't track it down here. Is it possible you were using an event struct which hadn't been passed to event_set() yet (just a sanity check for a simple bug)? > However, it's useful to suppress noise in valgrind output, and there's > no real cost to initializing ev_res at event_set time. Thus the attached > patch. Certainly agreed, except for the "noise" part (http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.uninitvals). -cl From provos at citi.umich.edu Sat Aug 4 22:15:27 2007 From: provos at citi.umich.edu (Niels Provos) Date: Sat Aug 4 22:15:30 2007 Subject: [Libevent-users] evhttp_dispatch_callback fix (so '/some?this=that' does not match '/something') In-Reply-To: <46B235F4.1050603@gratuitous.net> References: <46B0EEB2.10300@gratuitous.net> <46B235F4.1050603@gratuitous.net> Message-ID: <850f7cbe0708041915id61017au341632eb55c3595f@mail.gmail.com> Thank you. I love unit tests :-) Submitted to trunk. Niels. On 8/2/07, Elliot Foster wrote: > Here's a follow-up with a regression test (attached.) > > Elliot > > Elliot Foster wrote: > > Another quick fix for the dispatch callback, for when it goes through > > available callbacks looking for a match. The problem is that if the > > request URI has an argument, the comparison is done on the bytes before > > the url parameter separator. The result is that the lookup will result > > in mismatches, especially for a request URI like '/?some_arg=some_val' > > that will match the first callback found. > > > > Two potential fixes are attached, one that modifies the string to > > replace the argument separator with a null char before the strcmp, and > > another that checks for a null char in the potential match (at the same > > offset as the argument separator.) > > > > Thanks, > > > > Elliot > > > > > > ------------------------------------------------------------------------ > > > > _______________________________________________ > > Libevent-users mailing list > > Libevent-users@monkey.org > > http://monkey.org/mailman/listinfo/libevent-users > > > > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > > From slamb at slamb.org Sat Aug 4 22:21:46 2007 From: slamb at slamb.org (Scott Lamb) Date: Sat Aug 4 22:21:49 2007 Subject: [Libevent-users] [PATCH] initialize ev_res In-Reply-To: <20070805020429.GG17302@ns1.anodized.com> References: <469FC642.3040604@slamb.org> <20070805020429.GG17302@ns1.anodized.com> Message-ID: <46B5343A.2000109@slamb.org> Christopher Layne wrote: > On Thu, Jul 19, 2007 at 01:14:58PM -0700, Scott Lamb wrote: >> When I use "valgrind --tool=memcheck" on a libevent-based program, it >> gives the following complaint: >> >> ==15442== Conditional jump or move depends on uninitialised value(s) >> ==15442== at 0x4C0F2D3: event_add (event.c:632) >> ==15442== by 0x405EE4: main_loop (net.c:356) >> ==15442== by 0x411853: main (tincd.c:329) >> >> Here's the relevant portion of event.c: >> >> 632 if ((ev->ev_flags & EVLIST_ACTIVE) && >> 633 (ev->ev_res & EV_TIMEOUT)) { >> >> I've looked through the libevent code and verified that ev_res is always >> initialized when (ev_flags & EVLIST_ACTIVE) is true, so there's no real >> bug here. > > You wouldn't happen to have a copy of the code or atleast code segment > which was tickling this would you? > > When valgrind complains about uninitialised values, it's not in the fashion > of gcc in that "this could be uninitialised - so watch out" type of noise. It > really is an uninitalised area being read from. Yes, I also think it was really an uninitialized area being read from, but not one to worry about. As I'm sure you know, && indicates lazy evaluation - the second half doesn't get evaluated if the first half is false. But this was an optimized build of libevent, and I believe gcc decided that there were no side effects from evaluating (ev->ev_res & EV_TIMEOUT) early and that it would be faster to do the reads simultaneously, so it did so. gcc was almost right about "no side effects" - I don't blame it for not knowing that valgrind would complain about undefined values. valgrind is complaining about an intermediate value. Essentially, the code did "0 && junk". The *result* is correctly defined as 0. valgrind's just not quite smart enough to realize that though junk was loaded into a register, it didn't actually affect the result of a comparison or any other operation. Scott From clayne at anodized.com Sun Aug 5 02:00:43 2007 From: clayne at anodized.com (Christopher Layne) Date: Sun Aug 5 02:00:48 2007 Subject: [Libevent-users] [PATCH] initialize ev_res In-Reply-To: <46B5343A.2000109@slamb.org> References: <469FC642.3040604@slamb.org> <20070805020429.GG17302@ns1.anodized.com> <46B5343A.2000109@slamb.org> Message-ID: <20070805060043.GJ17302@ns1.anodized.com> On Sat, Aug 04, 2007 at 07:21:46PM -0700, Scott Lamb wrote: > Christopher Layne wrote: > >On Thu, Jul 19, 2007 at 01:14:58PM -0700, Scott Lamb wrote: > >>When I use "valgrind --tool=memcheck" on a libevent-based program, it > >>gives the following complaint: > >> > >>==15442== Conditional jump or move depends on uninitialised value(s) > >>==15442== at 0x4C0F2D3: event_add (event.c:632) > >>==15442== by 0x405EE4: main_loop (net.c:356) > >>==15442== by 0x411853: main (tincd.c:329) > >> > >>Here's the relevant portion of event.c: > >> > >>632 if ((ev->ev_flags & EVLIST_ACTIVE) && > >>633 (ev->ev_res & EV_TIMEOUT)) { > >> > >>I've looked through the libevent code and verified that ev_res is always > >>initialized when (ev_flags & EVLIST_ACTIVE) is true, so there's no real > >>bug here. > > > >You wouldn't happen to have a copy of the code or atleast code segment > >which was tickling this would you? > > Yes, I also think it was really an uninitialized area being read from, > but not one to worry about. > > As I'm sure you know, && indicates lazy evaluation - the second half > doesn't get evaluated if the first half is false. But this was an Right. However my point (in regards to splitting the conditional) was due to the ambiguity of multiple options when valgrind complains about a single line which has more than one possibility: 1. ev_flags is uninitialised (but when masked, result just happens to be true). + ev_res is uninitialised, valgrind complains about line 632. 2. ev_flags is uninitialised, mask results false, ev_res never touched, valgrind complains about line 632. 3. ev_flags is initialised, mask results true, ev_res is uninitialised, valgrind complains about line 632. 4. ev_flags is initialised, mask results false, ev_res never touched. See where I was going with that now? The code may indicate all day that ev_flags should always be initialised before even hitting event_add, but that doesn't stop other things from happening, like half your DRAM being 0x0, your CPU melting, straight up bugs, etc. I'm sure you get the drift. > optimized build of libevent, and I believe gcc decided that there were > no side effects from evaluating (ev->ev_res & EV_TIMEOUT) early and that > it would be faster to do the reads simultaneously, so it did so. gcc was > almost right about "no side effects" - I don't blame it for not knowing > that valgrind would complain about undefined values. > > valgrind is complaining about an intermediate value. Essentially, the > code did "0 && junk". The *result* is correctly defined as 0. valgrind's > just not quite smart enough to realize that though junk was loaded into > a register, it didn't actually affect the result of a comparison or any > other operation. > > Scott I still do not believe this to be valgrind's fault. Valgrind surely knows exactly what is going on with registers as it is emulating them. (http://valgrind.org/docs/manual/mc-tech-docs.html#mc-tech-docs.storage) I basically was just curious how you got it to come about, because I also tried various optimization combinations of both libevent (ev_res not init'd) and test code to try and see this and was unsuccessful in doing so. Valgrind never indicated an error. Now if I explicitly did not pass the event struct to event_set() before hand, then yes errors were visible. But for the most part, depending on how much trash was in memory at the time, they wouldn't make it past the first assert(). The issue though is that in your case, it might not have even been on the stack, or an entirely different scenario - which is what got me asking in the first place. I just think it's unsafe to write things off as "valgrind noise" when said noise could actually indicate a "should not happen." -cl From slamb at slamb.org Sun Aug 5 02:19:57 2007 From: slamb at slamb.org (Scott Lamb) Date: Sun Aug 5 02:20:43 2007 Subject: [Libevent-users] [PATCH] initialize ev_res In-Reply-To: <20070805060043.GJ17302@ns1.anodized.com> References: <469FC642.3040604@slamb.org> <20070805020429.GG17302@ns1.anodized.com> <46B5343A.2000109@slamb.org> <20070805060043.GJ17302@ns1.anodized.com> Message-ID: <46B56C0D.1030702@slamb.org> Christopher Layne wrote: > On Sat, Aug 04, 2007 at 07:21:46PM -0700, Scott Lamb wrote: >> Christopher Layne wrote: >>> On Thu, Jul 19, 2007 at 01:14:58PM -0700, Scott Lamb wrote: >>>> When I use "valgrind --tool=memcheck" on a libevent-based program, it >>>> gives the following complaint: >>>> >>>> ==15442== Conditional jump or move depends on uninitialised value(s) >>>> ==15442== at 0x4C0F2D3: event_add (event.c:632) >>>> ==15442== by 0x405EE4: main_loop (net.c:356) >>>> ==15442== by 0x411853: main (tincd.c:329) >>>> >>>> Here's the relevant portion of event.c: >>>> >>>> 632 if ((ev->ev_flags & EVLIST_ACTIVE) && >>>> 633 (ev->ev_res & EV_TIMEOUT)) { >>>> >>>> I've looked through the libevent code and verified that ev_res is always >>>> initialized when (ev_flags & EVLIST_ACTIVE) is true, so there's no real >>>> bug here. >>> You wouldn't happen to have a copy of the code or atleast code segment >>> which was tickling this would you? >> Yes, I also think it was really an uninitialized area being read from, >> but not one to worry about. >> >> As I'm sure you know, && indicates lazy evaluation - the second half >> doesn't get evaluated if the first half is false. But this was an > > Right. However my point (in regards to splitting the conditional) was due > to the ambiguity of multiple options when valgrind complains about a single > line which has more than one possibility: > > 1. ev_flags is uninitialised (but when masked, result just happens to be true). > + ev_res is uninitialised, valgrind complains about line 632. > 2. ev_flags is uninitialised, mask results false, ev_res never touched, valgrind > complains about line 632. > 3. ev_flags is initialised, mask results true, ev_res is uninitialised, valgrind > complains about line 632. > 4. ev_flags is initialised, mask results false, ev_res never touched. > > See where I was going with that now? The code may indicate all day that > ev_flags should always be initialised before even hitting event_add, but that > doesn't stop other things from happening, like half your DRAM being 0x0, > your CPU melting, straight up bugs, etc. I'm sure you get the drift. Well, splitting the conditional won't help - line numbers in optimized builds don't really make sense anyway; it jumps all over the place. This only happens on optimized 64-bit builds (in which the optimization makes sense because ev_flags and ev_res are in the same word). If you have such a machine, you can reproduce it with this trivial program: [slamb@rosalyn ~]$ cat test.c #include #include int main(int argc, char **argv) { struct event *ev; ev = malloc(sizeof(struct event)); if (ev == NULL) abort(); ev->ev_flags = 0; if ((ev->ev_flags & EVLIST_ACTIVE) && (ev->ev_res & EV_TIMEOUT)) { abort(); } return 0; } [slamb@rosalyn ~]$ uname -a Linux rosalyn.zorg.slamb.org 2.6.18-8.el5xen #1 SMP Thu Mar 15 19:56:43 EDT 2007 x86_64 x86_64 x86_64 GNU/Linux [slamb@rosalyn ~]$ gcc --version gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [slamb@rosalyn ~]$ valgrind --version valgrind-3.2.1 [slamb@rosalyn ~]$ gcc -Wall -O2 test.c -o test [slamb@rosalyn ~]$ valgrind --tool=memcheck ./test ...boilerplate... ==24325== Conditional jump or move depends on uninitialised value(s) ==24325== at 0x400504: main (in /home/slamb/test) ... [slamb@rosalyn ~]$ gcc -Wall test.c -o test [slamb@rosalyn ~]$ valgrind --tool=memcheck ./test ...boilerplate only... You'll notice the same thing does not happen on a 32-bit machine. slamb@spiff-centos5 ~]$ uname -a Linux spiff-centos5 2.6.23-rc1 #8 SMP Fri Jul 27 21:02:53 PDT 2007 i686 i686 i386 GNU/Linux [slamb@spiff-centos5 ~]$ gcc --version gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [slamb@spiff-centos5 ~]$ valgrind --version valgrind-3.2.1 [slamb@spiff-centos5 ~]$ gcc -Wall -O2 test.c -o test [slamb@spiff-centos5 ~]$ valgrind --tool=memcheck ./test ...boilerplate only... [slamb@spiff-centos5 ~]$ gcc -Wall test.c -o test [slamb@spiff-centos5 ~]$ valgrind --tool=memcheck ./test ...boilerplate only... > I still do not believe this to be valgrind's fault. Valgrind surely knows exactly > what is going on with registers as it is emulating them. > (http://valgrind.org/docs/manual/mc-tech-docs.html#mc-tech-docs.storage) It's not quite sophisticated enough to realize that despite boolean operations before performed on junk, they can never actually influence the result. > I basically was just curious how you got it to come about, because I also > tried various optimization combinations of both libevent (ev_res not init'd) > and test code to try and see this and was unsuccessful in doing so. Valgrind > never indicated an error. Now if I explicitly did not pass the event struct > to event_set() before hand, then yes errors were visible. But for the most > part, depending on how much trash was in memory at the time, they wouldn't > make it past the first assert(). The issue though is that in your case, it > might not have even been on the stack, or an entirely different scenario - > which is what got me asking in the first place. I just think it's unsafe > to write things off as "valgrind noise" when said noise could actually > indicate a "should not happen." From slamb at slamb.org Sun Aug 5 02:32:54 2007 From: slamb at slamb.org (Scott Lamb) Date: Sun Aug 5 02:33:39 2007 Subject: [Libevent-users] [PATCHES] use monotonic clock & infinite timeouts In-Reply-To: <850f7cbe0707301541u75d96a5y88c50c56fe0879a7@mail.gmail.com> References: <46A7AA43.7010009@slamb.org> <46A7E905.1050600@slamb.org> <850f7cbe0707301541u75d96a5y88c50c56fe0879a7@mail.gmail.com> Message-ID: <46B56F16.8070704@slamb.org> Niels Provos wrote: > Thanks for the patches. I removed the default timeout. Your patch > had a bug where timeout_correct no longer set event_tv correctly. I > fixed that. Oh, nice catch, thanks. > Unfortunatley, the regression test currently fails on Mac > OS X when compiled with -O2. Still trying to figure that one out. Hmm, I'm seeing failures, too. This one on OS X: Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000034 http_postrequest_done (req=0x0, arg=0x0) at regress_http.c:520 520 if (req->response_code != HTTP_OK) { (gdb) bt #0 http_postrequest_done (req=0x0, arg=0x0) at regress_http.c:520 #1 0x00026d87 in evhttp_connection_fail (evcon=0x300540, error=EVCON_HTTP_TIMEOUT) at http.c:522 #2 0x000227ab in event_base_loop (base=0x300180, flags=0) at event.c:331 #3 0x00022a2f in event_loop (flags=0) at event.c:381 #4 0x00022a47 in event_dispatch () at event.c:345 #5 0x00004bbf in http_post_test () at regress_http.c:468 #6 0x0000554a in http_suite () at regress_http.c:728 #7 0x00003f12 in main (argc=1, argv=0xbffff3ac) at regress.c:1052 Here's the relevant bit from frame #1: 521 if (req->cb != NULL) 522 (*req->cb)(NULL, req->cb_arg); So that test will cause bus errors any time the http connection fails. Any particular reason it's passing NULL here rather than req? It hasn't been deleted yet. Haven't checked why the connection failed, and there's some different failure (also in HTTP) on Linux. I might look more closely when I'll less sleepy. Best regards, Scott From slamb at slamb.org Sun Aug 5 02:40:13 2007 From: slamb at slamb.org (Scott Lamb) Date: Sun Aug 5 02:41:03 2007 Subject: [PATCH] Re: [Libevent-users] rtsig doesn't compile - remove? In-Reply-To: <850f7cbe0707301543g58c1e2b0s4b83787bb1cc69fa@mail.gmail.com> References: <46A6F233.9040408@slamb.org> <850f7cbe0707301543g58c1e2b0s4b83787bb1cc69fa@mail.gmail.com> Message-ID: <46B570CD.8010301@slamb.org> Niels Provos wrote: > I am fine with removing rtsig. I personally never liked that way to > do event notification. If someone feels strongly, they can revive it > from svn and fix it. Here's a patch to remove it, including the associated autoconf gunk. Scott -------------- next part -------------- >From a5d264a55153e029e58eebb60840f0ed17a81071 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Tue, 31 Jul 2007 14:41:38 -0700 Subject: [PATCH] remove rtsig, which is obsolete and broken --- libevent/Makefile.am | 2 +- libevent/WIN32-Code/config.h | 6 - libevent/configure.in | 53 --- libevent/event.c | 6 - libevent/rtsig.c | 997 ------------------------------------------ libevent/test/test.sh | 7 - 6 files changed, 1 insertions(+), 1070 deletions(-) delete mode 100644 libevent/rtsig.c diff --git a/libevent/Makefile.am b/libevent/Makefile.am index f88f8a1..e8aacac 100644 --- a/libevent/Makefile.am +++ b/libevent/Makefile.am @@ -6,7 +6,7 @@ bin_SCRIPTS = event_rpcgen.py EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h evdns.3 \ evrpc.h evrpc-internal.h \ event.3 \ - kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \ + kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \ evport.c devpoll.c event_rpcgen.py \ sample/Makefile.am sample/Makefile.in sample/event-test.c \ sample/signal-test.c sample/time-test.c \ diff --git a/libevent/WIN32-Code/config.h b/libevent/WIN32-Code/config.h index aed9774..21ccc5b 100644 --- a/libevent/WIN32-Code/config.h +++ b/libevent/WIN32-Code/config.h @@ -115,9 +115,6 @@ /* Define if you have the header file. */ #undef HAVE_POLL_H -/* Define if your system supports POSIX realtime signals */ -#undef HAVE_RTSIG - /* Define if you have the `select' function. */ #undef HAVE_SELECT @@ -184,9 +181,6 @@ /* Define if kqueue works correctly with pipes */ #undef HAVE_WORKING_KQUEUE -/* Define if realtime signals work on pipes */ -#undef HAVE_WORKING_RTSIG - /* Name of package */ #define PACKAGE "libevent" diff --git a/libevent/configure.in b/libevent/configure.in index 399d61e..623fac1 100644 --- a/libevent/configure.in +++ b/libevent/configure.in @@ -29,11 +29,6 @@ dnl the command line with --enable-shared and --disable-shared. dnl AC_DISABLE_SHARED AC_SUBST(LIBTOOL_DEPS) -dnl Check for optional stuff -AC_ARG_WITH(rtsig, - [ --with-rtsig compile with support for real time signals (experimental)], - [usertsig=yes], [usertsig=no]) - dnl Checks for libraries. AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(resolv, inet_aton) @@ -163,58 +158,10 @@ if test "x$haveselect" = "xyes" ; then fi havepoll=no -havertsig=no AC_CHECK_FUNCS(poll, [havepoll=yes], ) if test "x$havepoll" = "xyes" ; then AC_LIBOBJ(poll) needsignal=yes - - if test "x$usertsig" = "xyes" ; then - AC_CHECK_FUNCS(sigtimedwait, [havertsig=yes], ) - fi -fi -if test "x$havertsig" = "xyes" ; then - AC_MSG_CHECKING(for F_SETSIG in fcntl.h) - AC_EGREP_CPP(yes, -[ -#define _GNU_SOURCE -#include -#ifdef F_SETSIG -yes -#endif -], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no); havertsig=no]) -fi -if test "x$havertsig" = "xyes" ; then - AC_DEFINE(HAVE_RTSIG, 1, [Define if your system supports POSIX realtime signals]) - AC_LIBOBJ(rtsig) - AC_MSG_CHECKING(for working rtsig on pipes) - AC_TRY_RUN( -[ -#define _GNU_SOURCE -#include -#include -#include - -int sigio() -{ - exit(0); -} - -int main() -{ - int fd[2]; - - pipe(fd); - signal(SIGIO, sigio); - fcntl(fd[0], F_SETOWN, getpid()); - fcntl(fd[0], F_SETSIG, SIGIO); - fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_ASYNC); - write(fd[1], "", 1); - return 1; -} -], [ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_WORKING_RTSIG, 1, [Define if realtime signals work on pipes])], - AC_MSG_RESULT(no)) fi haveepoll=no diff --git a/libevent/event.c b/libevent/event.c index 2af11a7..ab13664 100644 --- a/libevent/event.c +++ b/libevent/event.c @@ -66,9 +66,6 @@ extern const struct eventop selectops; #ifdef HAVE_POLL extern const struct eventop pollops; #endif -#ifdef HAVE_RTSIG -extern const struct eventop rtsigops; -#endif #ifdef HAVE_EPOLL extern const struct eventop epollops; #endif @@ -96,9 +93,6 @@ const struct eventop *eventops[] = { #ifdef HAVE_DEVPOLL &devpollops, #endif -#ifdef HAVE_RTSIG - &rtsigops, -#endif #ifdef HAVE_POLL &pollops, #endif diff --git a/libevent/rtsig.c b/libevent/rtsig.c deleted file mode 100644 index e0e55af..0000000 --- a/libevent/rtsig.c +++ /dev/null @@ -1,997 +0,0 @@ -/* - * Copyright (c) 2006 Mathew Mills - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Meta-level comments: You know that a kernel interface is wrong if - * supporting it requires three times more code than any of the other - * kernel interfaces supported in libevent. Niels - 2006-02-22 - */ -/** - - "RTSIG" is a shorthand for using O_ASYNC to make descriptors send - signals when readable/writable and to use POSIX real-time signals - witch are queued unlike normal signals. At first blush this may - seem like a alternative to epoll, but a number of problems arise - when attempting to build an eventloop entirely out of rtsig. - Still, we can use rtsig in combination with poll() to - provide an eventloop that allows for many thousands of sockets - without huge overheads implicit with using select() or poll() - alone. epoll and kqueue are far superior to rtsig and should be - used where available, but rtsig has been in standard Linux kernels - for a long time and have a huge installation base. epoll requires - special patches for 2.4 kernels and 2.6 kernels are not yet nearly - so ubiquitous. - - rtsig problems: - - O_ASYNC mechanisms work only on sockets - not pipes or tty's - - - O_ASYNC signals are edge-triggered, POLLIN on packet arriving - or socket close; POLLOUT when a socket transitions from - non-writable to writable. Being edge-triggered means the - event-handler callbacks must transition the level ( reading - completely the socket buffer contents ) or it will be unable to - reliably receive notification again. - - - rtsig implementations must be intimately involved in how a - process dispatches signals. - - - delivering signals per-event can be expensive, CPU-wise, but - sigtimedwait() blocks on signals only and means non-sockets - cannot be serviced. - - Theory of operation: - This libevent module uses rtsig to allow us to manage a set of - poll-event descriptors. We can drop uninteresting fd's from the - pollset if the fd will send a signal when it becomes interesting - again. - - poll() offers us level-triggering and, when we have verified the - level of a socket, we can trust the edge-trigger nature of the - ASYNC signal. - - As an eventloop we must poll for external events but leverage - kernel functionality to sleep between events ( until the loop's - next scheduled timed event ). - - If we are polling on any non-sockets then we simply have no choice - about blocking on the poll() call. If we blocked on the - sigtimedwait() call as rtsig papers recommend we will not wake on - non-socket state transitions. As part of libevent, this module - must support non-socket polling. - - Many applications, however, do not need to poll on non-sockets and - so this module should be able to optimize this case by using - sigtimedwait(). For this reason this module can actually trigger - events in each of three different ways: - - poll() returning ready events from descriptors in the pollset - - - real-time signals dequeued via sigtimedwait() - - - real-time signals that call an installed signal handler which in - turn writes the contents of siginfo to one end of a socketpair - DGRAM socket. The other end of the socket is always in the - pollset so poll will be guaranteed to return even if the signal is - received before entering poll(). - - non-socket descriptors force us to block on the poll() for the - duration of a dispatch. In this case we unblock (w/ sigprocmask) - the managed signals just before polling. Each managed signal is - handled by signal_handler() which send()'s the contents of siginfo - over the socketpair. Otherwise, we call poll() with a timeout of - 0ms so it checks the levels of the fd's in the pollset and returns - immediately. Any fd that is a socket and has no active state is - removed from the pollset for the next pass -- we will rely on - getting a signal for events on these fd's. - - The receiving end of the siginfo socketpair is in the pollset - (permanently) so if we are polling on non-sockets, the delivery of - signals immediately following sigprocmask( SIG_UNBLOCK...) will - result in a readable op->signal_recv_fd which ensures the poll() - will return immediately. If the poll() call is blocking and a - signal arrives ( possibly a real-time signal from a socket not in - the pollset ) its handler will write the data to the socketpair - and interrupt the poll(). - - After every poll call we attempt a non-blocking recv from the - signal_recv_fd and continue to recv and dispatch the events until - recv indicates the socket buffer is empty. - - One might raise concerns about receiving event activations from - both poll() and from the rtsig data in the signal_recv_fd. - Fortunately, libevent is already structured for event coalescing, - so this issue is mitigated ( though we do some work twice for the - same event making us less efficient ). I suspect that the cost of - turning off the O_ASYNC flag on fd's in the pollset is more - expensive than handling some events twice. Looking at the - kernel's source code for setting O_ASYNC, it looks like it takes a - global kernel lock... - - After a poll and recv-loop for the signal_recv_fd, we finally do a - sigtimedwait(). sigtimedwait will only block if we haven't - blocked in poll() and we have not enqueued events from either the - poll or the recv-loop. Because sigtimedwait blocks all signals - that are not in the set of signals to be dequeued, we need to - dequeue almost all signals and make sure we dispatch them - correctly. We dequeue any signal that is not blocked as well as - all libevent-managed signals. If we get a signal that is not - managed by libevent we lookup the sigaction for the specific - signal and call that function ourselves. - - Finally, I should mention that getting a SIGIO signal indicates - that the rtsig buffer has overflowed and we have lost events. - This forces us to add _every_ descriptor to the pollset to recover. - -*/ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* Enable F_SETSIG and F_SETOWN */ -#define _GNU_SOURCE - -#include -#ifdef HAVE_SYS_TIME_H -#include -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "event.h" -#include "event-internal.h" -#include "log.h" -extern struct event_list signalqueue; - -#include -#ifndef __NR_gettid -#define gettid() getpid() -#else - -#if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3))) -_syscall0(pid_t,gettid) -#endif - -#endif - -#define EVLIST_NONSOCK 0x1000 /* event is for a non-socket file-descriptor */ -#define EVLIST_DONTDEL 0x2000 /* event should always be in the pollset */ -#define MAXBUFFERSIZE (1024 * 1024 * 2) /* max socketbuffer for signal-spair */ -#define INIT_MAX 16 /* init/min # of fd positions in our pollset */ - -static int signal_send_fd[_NSIG]; /* the globalend of the signal socketpair */ -static int trouble[_NSIG]; /* 1 when signal-handler cant send to signal_send_fd */ - -struct rtdata; -TAILQ_HEAD(rtdata_list, rtdata); - -struct rtsigop { - sigset_t sigs; /* signal mask for all _managed_ signals */ - struct pollfd *poll; /* poll structures */ - struct rtdata **ptodat; /* map poll_position to rtdata */ - int cur; /* cur # fd's in a poll set */ - int max; /* max # fd's in a poll set, start at 16 and grow as needed */ - int total; /* count of fd's we are watching now */ - int signo; /* the signo we use for ASYNC fd notifications */ - int nonsock; /* number of non-socket fd's we are watching */ - int highestfd; /* highest fd accomodated by fdtodat */ - struct rtdata_list **fdtodat; /* map fd to rtdata ( and thus to event ) */ - int signal_recv_fd; /* recv side of the signal_send_fd */ - int signal_send_fd; /* recv side of the signal_send_fd */ - struct event sigfdev; /* our own event structure for the signal fd */ -}; - -struct rtdata { - /* rtdata holds rtsig-private state on each event */ - TAILQ_ENTRY (rtdata) next; - struct event *ev; - int poll_position; -}; - -void *rtsig_init(struct event_base *); -int rtsig_add(void *, struct event *); -int rtsig_del(void *, struct event *); -int rtsig_recalc(struct event_base *, void *, int); -int rtsig_dispatch(struct event_base *, void *, struct timeval *); - -struct eventop rtsigops = { - "rtsig", - rtsig_init, - rtsig_add, - rtsig_del, - rtsig_recalc, - rtsig_dispatch -}; - -static void -signal_handler(int sig, siginfo_t *info, void *ctx) -{ - /* - * the signal handler for all libevent-managed signals only - * used if we need to do a blocking poll() call due to - * non-socket fd's in the pollset. - */ - - siginfo_t *i = info; - siginfo_t i_local; - - if (trouble[sig - 1]) { - i_local.si_signo = SIGIO; - i_local.si_errno = 0; - i_local.si_code = 0; - i = &i_local; - trouble[sig - 1] = 0; - } - - if (send(signal_send_fd[sig - 1], i, sizeof(*i), - MSG_DONTWAIT|MSG_NOSIGNAL) == -1) - trouble[sig - 1] = 1; -} - -static void -donothing(int fd, short event, void *arg) -{ - /* - * callback for our signal_recv_fd event structure - * we don't want to act on these events, we just want to wake the poll() - */ -}; - -static void -signotset(sigset_t *set) -{ - int i, l; - l = sizeof(*set) / 4; - for (i = 0; i < l; i++) { - ((unsigned *)set)[i] = ~((unsigned *)set)[i]; - } -} - -/* The next three functions manage our private data about each event struct */ - -static int -grow_fdset(struct rtsigop *op, int newhigh) -{ - /* - * grow the fd -> rtdata array because we have encountered a - * new fd too high to fit in the existing array - */ - - struct rtdata_list **p; - struct rtdata_list *datset; - int i,x; - int newcnt = (newhigh + 1) << 1; - - if (newhigh <= op->highestfd) - return (0); - - p = op->fdtodat; - p = realloc(op->fdtodat, sizeof(struct rtdata_list *) * newcnt); - if (p == NULL) - return (-1); - op->fdtodat = p; - - datset = calloc(newcnt - (op->highestfd + 1), - sizeof(struct rtdata_list)); - if (datset == NULL) - return (-1); - - for (i = op->highestfd + 1, x = 0; i < newcnt; i++, x++) { - op->fdtodat[i] = &(datset[x]); - TAILQ_INIT(op->fdtodat[i]); - } - - op->highestfd = newcnt - 1; - return (0); -} - -static struct rtdata * -ev2dat(struct rtsigop *op, struct event *ev, int create) -{ - /* - * given an event struct, find the dat structure that - * corresponds to it if create is non-zero and the rtdata - * structure does not exist, create it return NULL if not - * found - */ - - int found = 0; - int fd = ev->ev_fd; - struct rtdata *ret = NULL; - - if (op->highestfd < fd && create) - if (grow_fdset(op, fd) == -1) - return (NULL); - - TAILQ_FOREACH(ret, op->fdtodat[fd], next) { - if (ret->ev == ev) { - found = 1; - break; - } - } - - if (!found) { - if (!create) - return (NULL); - - ret = calloc(1, sizeof(struct rtdata)); - if (ret == NULL) - return (NULL); - ret->ev = ev; - ret->poll_position = -1; - TAILQ_INSERT_TAIL(op->fdtodat[fd], ret, next); - } - - return (ret); -} - -static void -dat_del(struct rtsigop *op, struct rtdata *dat) -{ - /* - * delete our private notes about a given event struct - * called from rtsig_del() only - */ - int fd; - if (dat == NULL) - return; - fd = dat->ev->ev_fd; - - TAILQ_REMOVE(op->fdtodat[fd], dat, next); - memset(dat, 0, sizeof(*dat)); - free(dat); -} - - -static void -set_sigaction(int sig) -{ - /* - * set the standard handler for any libevent-managed signal, - * including the rtsig used for O_ASYNC notifications - */ - struct sigaction act; - - act.sa_flags = SA_RESTART | SA_SIGINFO; - sigfillset(&(act.sa_mask)); - act.sa_sigaction = &signal_handler; - sigaction(sig, &act, NULL); -} - -static int -find_rt_signal() -{ - /* find an unused rtsignal */ - struct sigaction act; - int sig = SIGRTMIN; - - while (sig <= SIGRTMAX) { - if (sigaction(sig, NULL, &act) != 0) { - if (errno == EINTR) - continue; - } else { - if (act.sa_flags & SA_SIGINFO) { - if (act.sa_sigaction == NULL) - return (sig); - } else { - if (act.sa_handler == SIG_DFL) - return (sig); - } - } - sig++; - } - return (0); -} - -/* - * the next three functions manage our pollset and the memory management for - * fd -> rtdata -> event -> poll_position maps - */ - -static int -poll_add(struct rtsigop *op, struct event *ev, struct rtdata *dat) -{ - struct pollfd *pfd; - int newmax = op->max << 1; - int pp; - - if (op->poll == NULL) - return (0); - - if (dat == NULL) - dat = ev2dat(op, ev, 0); - - if (dat == NULL) - return (0); - - pp = dat->poll_position; - - if (pp != -1) { - pfd = &op->poll[pp]; - if (ev->ev_events & EV_READ) - pfd->events |= POLLIN; - - if (ev->ev_events & EV_WRITE) - pfd->events |= POLLOUT; - - return (0); - } - - if (op->cur == op->max) { - void *p = realloc(op->poll, sizeof(*op->poll) * newmax); - if (p == NULL) { - errno = ENOMEM; - return (-1); - } - op->poll = p; - - p = realloc(op->ptodat, sizeof(*op->ptodat) * newmax); - if (p == NULL) { - /* shrink the pollset back down */ - op->poll = realloc(op->poll, - sizeof(*op->poll) * op->max); - errno = ENOMEM; - return (-1); - } - op->ptodat = p; - op->max = newmax; - } - - pfd = &op->poll[op->cur]; - pfd->fd = ev->ev_fd; - pfd->revents = 0; - pfd->events = 0; - - if (ev->ev_events & EV_READ) - pfd->events |= POLLIN; - - if (ev->ev_events & EV_WRITE) - pfd->events |= POLLOUT; - - op->ptodat[op->cur] = dat; - dat->poll_position = op->cur; - op->cur++; - - return (0); -} - -static void -poll_free(struct rtsigop *op, int n) -{ - if (op->poll == NULL) - return; - - op->cur--; - - if (n < op->cur) { - memcpy(&op->poll[n], &op->poll[op->cur], sizeof(*op->poll)); - op->ptodat[n] = op->ptodat[op->cur]; - op->ptodat[n]->poll_position = n; - } - - - /* less then half the max in use causes us to shrink */ - if (op->max > INIT_MAX && op->cur < op->max >> 1) { - op->max >>= 1; - op->poll = realloc(op->poll, sizeof(*op->poll) * op->max); - op->ptodat = realloc(op->ptodat, sizeof(*op->ptodat) * op->max); - } -} - -static void -poll_remove(struct rtsigop *op, struct event *ev, struct rtdata *dat) -{ - int pp; - if (dat == NULL) - dat = ev2dat(op, ev, 0); - - if (dat == NULL) return; - - pp = dat->poll_position; - if (pp != -1) { - poll_free(op, pp); - dat->poll_position = -1; - } -} - -static void -activate(struct event *ev, int flags) -{ - /* activate an event, possibly removing one-shot events */ - if (!(ev->ev_events & EV_PERSIST)) - event_del(ev); - event_active(ev, flags, 1); -} - -#define FD_CLOSEONEXEC(x) do { \ - if (fcntl(x, F_SETFD, 1) == -1) \ - event_warn("fcntl(%d, F_SETFD)", x); \ -} while (0) - -void * -rtsig_init(struct event_base *) -{ - struct rtsigop *op; - int sockets[2]; - int optarg; - struct rtdata *dat; - int flags; - - if (getenv("EVENT_NORTSIG")) - goto err; - - op = calloc(1, sizeof(*op)); - if (op == NULL) - goto err; - - op->max = INIT_MAX; - op->poll = malloc(sizeof(*op->poll) * op->max); - if (op->poll == NULL) - goto err_free_op; - - op->signo = find_rt_signal(); - if (op->signo == 0) - goto err_free_poll; - - op->nonsock = 0; - - if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sockets) != 0) - goto err_free_poll; - - FD_CLOSEONEXEC(sockets[0]); - FD_CLOSEONEXEC(sockets[1]); - - signal_send_fd[op->signo - 1] = sockets[0]; - trouble[op->signo - 1] = 0; - op->signal_send_fd = sockets[0]; - op->signal_recv_fd = sockets[1]; - flags = fcntl(op->signal_recv_fd, F_GETFL); - fcntl(op->signal_recv_fd, F_SETFL, flags | O_NONBLOCK); - - optarg = MAXBUFFERSIZE; - setsockopt(signal_send_fd[op->signo - 1], - SOL_SOCKET, SO_SNDBUF, - &optarg, sizeof(optarg)); - - optarg = MAXBUFFERSIZE; - setsockopt(op->signal_recv_fd, - SOL_SOCKET, SO_RCVBUF, - &optarg, sizeof(optarg)); - - op->highestfd = -1; - op->fdtodat = NULL; - if (grow_fdset(op, 1) == -1) - goto err_close_pair; - - op->ptodat = malloc(sizeof(*op->ptodat) * op->max); - if (op->ptodat == NULL) - goto err_close_pair; - - sigemptyset(&op->sigs); - sigaddset(&op->sigs, SIGIO); - sigaddset(&op->sigs, op->signo); - sigprocmask(SIG_BLOCK, &op->sigs, NULL); - set_sigaction(SIGIO); - set_sigaction(op->signo); - - event_set(&(op->sigfdev), op->signal_recv_fd, EV_READ|EV_PERSIST, - donothing, NULL); - op->sigfdev.ev_flags |= EVLIST_DONTDEL; - dat = ev2dat(op, &(op->sigfdev), 1); - poll_add(op, &(op->sigfdev), dat); - - return (op); - - err_close_pair: - close(op->signal_recv_fd); - close(signal_send_fd[op->signo - 1]); - - err_free_poll: - free(op->poll); - - err_free_op: - free(op); - err: - return (NULL); -} - -int -rtsig_add(void *arg, struct event *ev) -{ - struct rtsigop *op = (struct rtsigop *) arg; - int flags, i; - struct stat statbuf; - struct rtdata *dat; - - if (ev->ev_events & EV_SIGNAL) { - int signo = EVENT_SIGNAL(ev); - - sigaddset(&op->sigs, EVENT_SIGNAL(ev)); - if (sigprocmask(SIG_BLOCK, &op->sigs, NULL) == -1) - return (-1); - - set_sigaction(signo); - - signal_send_fd[signo - 1] = op->signal_send_fd; - trouble[signo - 1] = 0; - - return (0); - } - - if (!(ev->ev_events & (EV_READ|EV_WRITE))) - return (0); - - if (-1 == fstat(ev->ev_fd, &statbuf)) - return (-1); - - if (!S_ISSOCK(statbuf.st_mode)) - ev->ev_flags |= EVLIST_NONSOCK; - - flags = fcntl(ev->ev_fd, F_GETFL); - if (flags == -1) - return (-1); - - if (!(flags & O_ASYNC)) { - if (fcntl(ev->ev_fd, F_SETSIG, op->signo) == -1 || - fcntl(ev->ev_fd, F_SETOWN, (int) gettid()) == -1) - return (-1); - - /* - * the overhead of always handling writeable edges - * isn't going to be that bad... - */ - if (fcntl(ev->ev_fd, F_SETFL, flags | O_ASYNC|O_RDWR)) - return (-1); - } - -#ifdef O_ONESIGFD - /* - * F_SETAUXFL and O_ONESIGFD are defined in a non-standard - * linux kernel patch to coalesce events for fds - */ - fcntl(ev->ev_fd, F_SETAUXFL, O_ONESIGFD); -#endif - - dat = ev2dat(op, ev, 1); - if (dat == NULL) - return (-1); - - op->total++; - if (ev->ev_flags & EVLIST_NONSOCK) - op->nonsock++; - - if (poll_add(op, ev, dat) == -1) { - /* must check the level of new fd's */ - i = errno; - fcntl(ev->ev_fd, F_SETFL, flags); - errno = i; - return (-1); - } - - return (0); -} - -int -rtsig_del(void *arg, struct event *ev) -{ - struct rtdata *dat; - struct rtsigop *op = (struct rtsigop *) arg; - - if (ev->ev_events & EV_SIGNAL) { - sigset_t sigs; - - sigdelset(&op->sigs, EVENT_SIGNAL(ev)); - - sigemptyset(&sigs); - sigaddset(&sigs, EVENT_SIGNAL(ev)); - return (sigprocmask(SIG_UNBLOCK, &sigs, NULL)); - } - - if (!(ev->ev_events & (EV_READ|EV_WRITE))) - return (0); - - dat = ev2dat(op, ev, 0); - poll_remove(op, ev, dat); - dat_del(op, dat); - op->total--; - if (ev->ev_flags & EVLIST_NONSOCK) - op->nonsock--; - - return (0); -} - -int -rtsig_recalc(struct event_base *base, void *arg, int max) -{ - return (0); -} - -/* - * the following do_X functions implement the different stages of a single - * eventloop pass: poll(), recv(sigsock), sigtimedwait() - * - * do_siginfo_dispatch() is a common factor to both do_sigwait() and - * do_signals_from_socket(). - */ - -static inline int -do_poll(struct rtsigop *op, struct timespec *ts, struct timespec **ts_p) -{ - int res = 0; - int i = 0; - - if (op->cur > 1) { - /* non-empty poll set (modulo the signalfd) */ - if (op->nonsock) { - int timeout = -1; - - if (*ts_p != NULL) - timeout = (*ts_p)->tv_nsec / 1000000 - + (*ts_p)->tv_sec * 1000; - - sigprocmask(SIG_UNBLOCK, &(op->sigs), NULL); - - res = poll(op->poll, op->cur, timeout); - - sigprocmask(SIG_BLOCK, &(op->sigs), NULL); - - ts->tv_sec = 0; - ts->tv_nsec = 0; - *ts_p = ts; - } else { - res = poll(op->poll, op->cur, 0); - } - - if (res < 0) { - return (errno == EINTR ? 0 : -1); - } else if (res) { - ts->tv_sec = 0; - ts->tv_nsec = 0; - *ts_p = ts; - } - - i = 0; - while (i < op->cur) { - struct rtdata *dat = op->ptodat[i]; - struct event *ev = dat->ev; - - if (op->poll[i].revents) { - int flags = 0; - - if (op->poll[i].revents & (POLLIN | POLLERR)) - flags |= EV_READ; - - if (op->poll[i].revents & POLLOUT) - flags |= EV_WRITE; - - if (!(ev->ev_events & EV_PERSIST)) { - poll_remove(op, ev, op->ptodat[i]); - event_del(ev); - } else { - i++; - } - - event_active(ev, flags, 1); - } else { - if (ev->ev_flags & (EVLIST_NONSOCK|EVLIST_DONTDEL)) { - i++; - } else { - poll_remove(op, ev, op->ptodat[i]); - } - } - } - } - return (res); -} - -static inline int -do_siginfo_dispatch(struct event_base *base, struct rtsigop *op, - siginfo_t *info) -{ - int signum; - struct rtdata *dat, *next_dat; - struct event *ev, *next_ev; - - if (info == NULL) - return (-1); - - signum = info->si_signo; - if (signum == op->signo) { - int flags, sigok = 0; - flags = 0; - - if (info->si_band & (POLLIN|POLLERR)) - flags |= EV_READ; - if (info->si_band & POLLOUT) - flags |= EV_WRITE; - - if (!flags) - return (0); - - if (info->si_fd > op->highestfd) - return (-1); - - dat = TAILQ_FIRST(op->fdtodat[info->si_fd]); - while (dat != TAILQ_END(op->fdtodat[info->si_fd])) { - next_dat = TAILQ_NEXT(dat, next); - if (flags & dat->ev->ev_events) { - ev = dat->ev; - poll_add(op, ev, dat); - activate(ev, flags & ev->ev_events); - sigok = 1; - } - dat = next_dat; - } - } else if (signum == SIGIO) { - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { - if (ev->ev_events & (EV_READ|EV_WRITE)) - poll_add(op, ev, NULL); - } - return (1); /* 1 means the caller should poll() again */ - - } else if (sigismember(&op->sigs, signum)) { - /* managed signals are queued */ - ev = TAILQ_FIRST(&signalqueue); - while (ev != TAILQ_END(&signalqueue)) { - next_ev = TAILQ_NEXT(ev, ev_signal_next); - if (EVENT_SIGNAL(ev) == signum) - activate(ev, EV_SIGNAL); - ev = next_ev; - } - } else { - /* dispatch unmanaged signals immediately */ - struct sigaction sa; - if (sigaction(signum, NULL, &sa) == 0) { - if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction) { - (*sa.sa_sigaction)(signum, info, NULL); - } else if (sa.sa_handler) { - if ((int)sa.sa_handler != 1) - (*sa.sa_handler)(signum); - } else { - if (signum != SIGCHLD) { - /* non-blocked SIG_DFL */ - kill(gettid(), signum); - } - } - } - } - - return (0); -} - -/* - * return 1 if we should poll again - * return 0 if we are all set - * return -1 on error - */ -static inline int -do_sigwait(struct event_base *base, struct rtsigop *op, - struct timespec *ts, struct timespec **ts_p, sigset_t *sigs) -{ - for (;;) { - siginfo_t info; - int signum; - - signum = sigtimedwait(sigs, &info, *ts_p); - - ts->tv_sec = 0; - ts->tv_nsec = 0; - *ts_p = ts; - - if (signum == -1) { - if (errno == EAGAIN || errno == EINTR) - return (0); - return (-1); - } else if (1 == do_siginfo_dispatch(base, op, &info)) { - return (1); - } - } - - /* NOTREACHED */ -} - -static inline int -do_signals_from_socket(struct event_base *base, struct rtsigop *op, - struct timespec *ts, struct timespec **ts_p) -{ - int fd = op->signal_recv_fd; - siginfo_t info; - int res; - - for (;;) { - res = recv(fd, &info, sizeof(info), MSG_NOSIGNAL); - if (res == -1) { - if (errno == EAGAIN) - return (0); - if (errno == EINTR) - continue; - return (-1); - } else { - ts->tv_sec = 0; - ts->tv_nsec = 0; - *ts_p = ts; - if (1 == do_siginfo_dispatch(base, op, &info)) - return (1); - } - } - /* NOTREACHED */ -} - -int -rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - struct rtsigop *op = (struct rtsigop *) arg; - struct timespec ts, *ts_p = NULL; - int res; - sigset_t sigs; - - if (tv != NULL) { - ts.tv_sec = tv->tv_sec; - ts.tv_nsec = tv->tv_usec * 1000; - *ts_p = ts; - } - - poll_for_level: - /* ts and ts_p can be modified in do_XXX() */ - res = do_poll(op, &ts, &ts_p); - - res = do_signals_from_socket(base, op, &ts, &ts_p); - if (res == 1) - goto poll_for_level; - else if (res == -1) - return (-1); - - /* - * the mask = managed_signals | unblocked-signals - * MM - if this is not blocking do we need to cast the net this wide? - */ - sigemptyset(&sigs); - sigprocmask(SIG_BLOCK, &sigs, &sigs); - signotset(&sigs); - sigorset(&sigs, &sigs, &op->sigs); - - res = do_sigwait(base, op, &ts, &ts_p, &sigs); - - if (res == 1) - goto poll_for_level; - else if (res == -1) - return (-1); - - return (0); -} - diff --git a/libevent/test/test.sh b/libevent/test/test.sh index 878d468..00ceec2 100755 --- a/libevent/test/test.sh +++ b/libevent/test/test.sh @@ -6,7 +6,6 @@ setup () { EVENT_NOPOLL=yes; export EVENT_NOPOLL EVENT_NOSELECT=yes; export EVENT_NOSELECT EVENT_NOEPOLL=yes; export EVENT_NOEPOLL - EVENT_NORTSIG=yes; export EVENT_NORTSIG } test () { @@ -76,12 +75,6 @@ echo "SELECT" test setup -unset EVENT_NORTSIG -export EVENT_NORTSIG -echo "RTSIG" -test - -setup unset EVENT_NOEPOLL export EVENT_NOEPOLL echo "EPOLL" -- 1.5.3.GIT From provos at citi.umich.edu Sun Aug 5 02:52:46 2007 From: provos at citi.umich.edu (Niels Provos) Date: Sun Aug 5 02:52:48 2007 Subject: [Libevent-users] [PATCHES] use monotonic clock & infinite timeouts In-Reply-To: <46B56F16.8070704@slamb.org> References: <46A7AA43.7010009@slamb.org> <46A7E905.1050600@slamb.org> <850f7cbe0707301541u75d96a5y88c50c56fe0879a7@mail.gmail.com> <46B56F16.8070704@slamb.org> Message-ID: <850f7cbe0708042352v572254f9v505bfb0183f19548@mail.gmail.com> On 8/4/07, Scott Lamb wrote: > Here's the relevant bit from frame #1: > > 521 if (req->cb != NULL) > 522 (*req->cb)(NULL, req->cb_arg); > > So that test will cause bus errors any time the http connection fails. > Any particular reason it's passing NULL here rather than req? It hasn't > been deleted yet. The NULL indicates that the request failed. The HTTP layer is going to free it up. However, the regression test is not expecting the request to fail and then dereferences a NULL pointer. Niels. From victor.box2 at globo.com Sun Aug 5 14:31:38 2007 From: victor.box2 at globo.com (Victor) Date: Sun Aug 5 15:31:12 2007 Subject: [Libevent-users] Newbie question about threads Message-ID: <200708051531.38246.victor.box2@globo.com> Hi there! I have a question regarding the use of libevent with threads. I have a thread running the event loop with its own event base and everything is working fine. Is it safe to call event_add() from a second thread to add more events on that event loop base? Thanks, Victor From mark at heily.com Sun Aug 5 23:30:10 2007 From: mark at heily.com (Mark Heily) Date: Sun Aug 5 23:30:22 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <200708051531.38246.victor.box2@globo.com> References: <200708051531.38246.victor.box2@globo.com> Message-ID: <1186371010.21676.36.camel@voltaire> On Sun, 2007-08-05 at 15:31 -0300, Victor wrote: > Is it safe to call event_add() from a second thread to > add more events on that event loop base? No. Two threads cannot modify the same event_base struct without explicit locking. You would need to use a mutex to protect the event_add() call. On a related note... I would like to see a threaded version of libevent that would give each thread it's own current_base variable. Right now, there is a global variable in event.c: struct event_base *current_base = NULL; A threaded library would use thread-specific data instead: static pthread_key_t *current_base_key; #define current_base \ ((struct event_base *) (pthread_get_specific(current_base_key)) This would allow you to use event_add(), event_dispatch(), and event_loop() in multiple threads in a natural way. Each thread would get it's own event loop automatically and not interfere with other threads' operation. You could also add internal protection within the event_base_() functions with mutexes so that two threads would not be able to modify the same event_base struct simultaneously. My suggestion is to name this threaded version of the library `libevent_r.a` and have a separate Makefile target to generate the threaded version. This second target would add -D_REENTRANT to the CFLAGS to enable all of the threaded codepaths. You would also need to link it with the pthreads library by adding -lpthread to the LDFLAGS. Returning to my previous example, you would modify event.c to look something like this: #if _REENTRANT static pthread_key_t *current_base_key; # define current_base \ ((struct event_base *) (pthread_get_specific(current_base_key)) #else struct event_base *current_base = NULL; #endif This approach allows both the threadsafe and non-threadsafe library to be built from the same source code. Niels, does this sound like something you would be willing to consider? If so, I would be willing to do the work and submit a patch. Regards, Mark From victor.box2 at globo.com Mon Aug 6 00:09:12 2007 From: victor.box2 at globo.com (Victor) Date: Mon Aug 6 00:10:14 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <1186371010.21676.36.camel@voltaire> References: <200708051531.38246.victor.box2@globo.com> <1186371010.21676.36.camel@voltaire> Message-ID: <200708060109.13419.victor.box2@globo.com> Hi Mark, On Monday 06 August 2007, Mark Heily wrote: > On Sun, 2007-08-05 at 15:31 -0300, Victor wrote: > > Is it safe to call event_add() from a second thread to > > add more events on that event loop base? > > No. Two threads cannot modify the same event_base struct without > explicit locking. You would need to use a mutex to protect the > event_add() call. > After reading your email, I thought that just adding mutex around event_add() will still not be safe, because when a event is processed, it is removed from the event queue and I cannot lock a mutex on that from outside libevent, am I right? Thanks for your answer. Victor From liusifan at gmail.com Mon Aug 6 01:45:38 2007 From: liusifan at gmail.com (lau stephen) Date: Mon Aug 6 01:45:45 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <200708051531.38246.victor.box2@globo.com> References: <200708051531.38246.victor.box2@globo.com> Message-ID: You can read the following links: http://monkeymail.org/archives/libevent-users/2007-January/000450.html Passing data between event loops in multithreaded apps http://monkeymail.org/archives/libevent-users/2006-October/000257.html 2007/8/6, Victor : > Hi there! > > I have a question regarding the use of libevent with threads. I have a > thread running the event loop with its own event base and everything > is working fine. Is it safe to call event_add() from a second thread to > add more events on that event loop base? > > Thanks, > > Victor > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > From provos at citi.umich.edu Mon Aug 6 11:28:39 2007 From: provos at citi.umich.edu (Niels Provos) Date: Mon Aug 6 11:28:51 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <1186371010.21676.36.camel@voltaire> References: <200708051531.38246.victor.box2@globo.com> <1186371010.21676.36.camel@voltaire> Message-ID: <850f7cbe0708060828w40014c1dnd05f201c326465af@mail.gmail.com> Hi Mark, I would like to figure out ways in which libevent can be more thread friendly without requiring everyone to use threads. So, thread specific store for the event base seems like a good idea and I would certainly appreciate to see patches. Niels. On 8/5/07, Mark Heily wrote: > On Sun, 2007-08-05 at 15:31 -0300, Victor wrote: > > Is it safe to call event_add() from a second thread to > > add more events on that event loop base? > > No. Two threads cannot modify the same event_base struct without > explicit locking. You would need to use a mutex to protect the > event_add() call. > > On a related note... > > I would like to see a threaded version of libevent that would give each > thread it's own current_base variable. Right now, there is a global > variable in event.c: > > struct event_base *current_base = NULL; > > A threaded library would use thread-specific data instead: > > static pthread_key_t *current_base_key; > #define current_base \ > ((struct event_base *) (pthread_get_specific(current_base_key)) > > This would allow you to use event_add(), event_dispatch(), and > event_loop() in multiple threads in a natural way. Each thread would get > it's own event loop automatically and not interfere with other threads' > operation. > > You could also add internal protection within the event_base_() > functions with mutexes so that two threads would not be able to modify > the same event_base struct simultaneously. > > My suggestion is to name this threaded version of the library > `libevent_r.a` and have a separate Makefile target to generate the > threaded version. This second target would add -D_REENTRANT to the > CFLAGS to enable all of the threaded codepaths. You would also need to > link it with the pthreads library by adding -lpthread to the LDFLAGS. > > Returning to my previous example, you would modify event.c to look > something like this: > > #if _REENTRANT > > static pthread_key_t *current_base_key; > # define current_base \ > ((struct event_base *) (pthread_get_specific(current_base_key)) > > #else > > struct event_base *current_base = NULL; > > #endif > > > This approach allows both the threadsafe and non-threadsafe library to > be built from the same source code. > > Niels, does this sound like something you would be willing to consider? > If so, I would be willing to do the work and submit a patch. > > Regards, > > Mark > > > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > From victor.box2 at globo.com Mon Aug 6 14:03:26 2007 From: victor.box2 at globo.com (Victor) Date: Mon Aug 6 14:04:38 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <850f7cbe0708060828w40014c1dnd05f201c326465af@mail.gmail.com> References: <200708051531.38246.victor.box2@globo.com> <1186371010.21676.36.camel@voltaire> <850f7cbe0708060828w40014c1dnd05f201c326465af@mail.gmail.com> Message-ID: <200708061503.26262.victor.box2@globo.com> Hi Niels, On Monday 06 August 2007, you wrote: > I would like to figure out ways in which libevent can be more thread > friendly without requiring everyone to use threads. So, thread > specific store for the event base seems like a good idea and I would > certainly appreciate to see patches. Just a quick thought: What about something simple like registering mutex lock/unlock callbacks? If there is registered mutex callbacks, libevent calls it before and after making changes on a event base. Something like: event_base_register_lock( event_base , myMutexlock ); event_base_register_unlock( event_base , myMutexunlock ); Regards, Victor From slamb at slamb.org Mon Aug 6 14:18:44 2007 From: slamb at slamb.org (Scott Lamb) Date: Mon Aug 6 14:18:46 2007 Subject: [Libevent-users] Newbie question about threads In-Reply-To: <200708061503.26262.victor.box2@globo.com> References: <200708051531.38246.victor.box2@globo.com> <1186371010.21676.36.camel@voltaire> <850f7cbe0708060828w40014c1dnd05f201c326465af@mail.gmail.com> <200708061503.26262.victor.box2@globo.com> Message-ID: <46B76604.4080709@slamb.org> Victor wrote: > Hi Niels, > > On Monday 06 August 2007, you wrote: >> I would like to figure out ways in which libevent can be more thread >> friendly without requiring everyone to use threads. So, thread >> specific store for the event base seems like a good idea and I would >> certainly appreciate to see patches. > > Just a quick thought: > > What about something simple like registering mutex lock/unlock > callbacks? If there is registered mutex callbacks, libevent calls it > before and after making changes on a event base. > > Something like: > event_base_register_lock( event_base , myMutexlock ); > event_base_register_unlock( event_base , myMutexunlock ); Ugh, no! If you were to share event bases between threads, this would not be adequate. Locks must be used around *all accesses* to a shared resources, not just *writes*. And if thread A alters an event base while thread B is dispatching on it, there needs to be a mechanism for thread A to wake thread B, unit tests of add/remove cases, etc. Secondly, it hasn't really been demonstrated that it's desirable to share event bases between threads (vs. having one per thread and some sort of balancing scheme). Given the added complexity to libevent, I don't think this case should be considered until someone gives a compelling reason. I've been meaning forever to do some benchmarks of different approaches, but...well...it hasn't happened, and I don't think a miracle is likely to happen in the next couple weeks. Too many things I want to do, too little time... With regards to Mark Heily's suggestion (current_base per thread), I would rather have no current_base at all. Specifically, I'd like event_set() or an event_set() workalike that does not do "ev->ev_base = current_base". This would ensure that if the caller forgets to call event_base_set(), the code will fail in an obvious way. I hate subtle failures that can creep in later. Best regards, Scott From kenstir at gmail.com Fri Aug 10 14:07:59 2007 From: kenstir at gmail.com (Ken Cox) Date: Fri Aug 10 14:08:12 2007 Subject: [Libevent-users] SEGV in compare (event_tree_RB_INSERT), or sometimes event_tree_RB_INSERT_COLOR Message-ID: I have a libevent program that wakes up every 20ms and does some processing. For this I use one event and repeatedly call event_add reusing the same event. In the field I see occasional crashes in event_tree_RB_INSERT or event_tree_RB_INSERT_COLOR, but I can't reproduce them in the lab or under valgrind. If you have seen this kind of crash, or can tell I'm doing something dreadfully wrong, or just can give me a general clue, I would greatly appreciate it. I built on r309 from the SVN trunk. Here's one such stack. Program terminated with signal 11, Segmentation fault. #0 compare (a=0x8648924, b=0x1) at event.c:136 136 event.c: No such file or directory. in event.c (gdb) bt #0 compare (a=0x8648924, b=0x1) at event.c:136 #1 0x08063bcd in event_tree_RB_INSERT (head=0x86481cc, elm=0x8648924) at event.c:170 #2 0x0806406e in event_queue_insert (base=0x86481a0, ev=0x8648924, queue=1) at event.c:847 #3 0x0806429e in event_add (ev=0x8648924, tv=0x86489d4) at event.c:635 #4 0x08055062 in process_cb (fd=-1, what=1, arg=0x86488b0) at foo.c:335 #5 0x080649a4 in event_base_loop (base=0x86481a0, flags=0) at event.c:313 #6 0x08064b4a in event_loop (flags=0) at event.c:364 #7 0x08064b62 in event_dispatch () at event.c:327 #8 0x08057d42 in main (argc=3, argv=0xbf985764) at foo.c:1061 The code looks kind of like this: struct event timer_ev; struct timeval next_wakeup_tv, snooze_tv; void process_once(void *arg) { } /* timer callback, invokes process_once and sets next timer */ void process_cb(int fd, short what, void *arg) { struct timeval now, then; struct timeval delta_tv = {0, 20000}; process_once(arg); /* calculate next wakeup time */ timeradd(&next_wakeup_tv, &delta_tv, &then); next_wakeup_tv = then; /* calculate snooze time until then; don't allow it to go negative */ gettimeofday(&now, NULL); if (timercmp(&then, &now, <)) timerclear(&snooze_tv); else timersub(&then, &now, &snooze_tv); /* snooze = then - now */ event_add(&timer_ev, &snooze_tv); fprintf(stderr, "%s: snooze={%lu, %6lu} next={%lu, %6lu}\n", __func__, snooze_tv.tv_sec, snooze_tv.tv_usec, next_wakeup_tv.tv_sec, next_wakeup_tv.tv_usec); } /* bootstrap timer */ void start(void *arg) { struct timeval now, delta_tv = {0, 20000}; event_set(&timer_ev, -1, 0, process_cb, arg); event_add(&timer_ev, &delta_tv); gettimeofday(&now, NULL); timeradd(&now, &delta_tv, &next_wakeup_tv); } == Ken From provos at citi.umich.edu Fri Aug 10 14:53:12 2007 From: provos at citi.umich.edu (Niels Provos) Date: Fri Aug 10 14:53:25 2007 Subject: [Libevent-users] Nick Mathewson joining as libevent maintainer Message-ID: <850f7cbe0708101153w953a54uc52c2919fdc98af1@mail.gmail.com> Hi everyone, I just wanted to let everyone know that Nick Mathewson is going to help with maintaining libevent. So, in the future, you have two people to bug about patches and bugs. Thanks, Niels. From kenstir at gmail.com Fri Aug 10 20:34:46 2007 From: kenstir at gmail.com (Ken Cox) Date: Fri Aug 10 20:35:08 2007 Subject: [Libevent-users] SEGV in compare (event_tree_RB_INSERT), or sometimes event_tree_RB_INSERT_COLOR In-Reply-To: References: Message-ID: Um, nevermind :) I finally was able to reproduce the problem in the lab and, well, it was my fault. It was a very occasional memory stomp. Sorry for the noise. Ken On Fri, 10 Aug 2007 14:07:59 -0400, Ken Cox wrote: > I have a libevent program that wakes up every 20ms and does some > processing. For this I use one event and repeatedly call event_add > reusing the same event. In the field I see occasional crashes in > event_tree_RB_INSERT or event_tree_RB_INSERT_COLOR, but I can't > reproduce them in the lab or under valgrind. > > If you have seen this kind of crash, or can tell I'm doing something > dreadfully wrong, or just can give me a general clue, I would greatly > appreciate it. > > I built on r309 from the SVN trunk. > > Here's one such stack. > > Program terminated with signal 11, Segmentation fault. > #0 compare (a=0x8648924, b=0x1) at event.c:136 > 136 event.c: No such file or directory. > in event.c > (gdb) bt > #0 compare (a=0x8648924, b=0x1) at event.c:136 > #1 0x08063bcd in event_tree_RB_INSERT (head=0x86481cc, elm=0x8648924) > at event.c:170 > #2 0x0806406e in event_queue_insert (base=0x86481a0, ev=0x8648924, > queue=1) at event.c:847 > #3 0x0806429e in event_add (ev=0x8648924, tv=0x86489d4) at event.c:635 > #4 0x08055062 in process_cb (fd=-1, what=1, arg=0x86488b0) at foo.c:335 > #5 0x080649a4 in event_base_loop (base=0x86481a0, flags=0) at > event.c:313 > #6 0x08064b4a in event_loop (flags=0) at event.c:364 > #7 0x08064b62 in event_dispatch () at event.c:327 > #8 0x08057d42 in main (argc=3, argv=0xbf985764) at foo.c:1061 > > The code looks kind of like this: > > struct event timer_ev; > struct timeval next_wakeup_tv, snooze_tv; > > void process_once(void *arg) > { > } > > /* timer callback, invokes process_once and sets next timer */ > void process_cb(int fd, short what, void *arg) > { > struct timeval now, then; > struct timeval delta_tv = {0, 20000}; > > process_once(arg); > > /* calculate next wakeup time */ > timeradd(&next_wakeup_tv, &delta_tv, &then); > next_wakeup_tv = then; > > /* calculate snooze time until then; don't allow it to go negative */ > gettimeofday(&now, NULL); > if (timercmp(&then, &now, <)) > timerclear(&snooze_tv); > else > timersub(&then, &now, &snooze_tv); /* snooze = then - now */ > event_add(&timer_ev, &snooze_tv); > > fprintf(stderr, "%s: snooze={%lu, %6lu} next={%lu, %6lu}\n", __func__, > snooze_tv.tv_sec, snooze_tv.tv_usec, > next_wakeup_tv.tv_sec, next_wakeup_tv.tv_usec); > } > > /* bootstrap timer */ > void start(void *arg) > { > struct timeval now, delta_tv = {0, 20000}; > event_set(&timer_ev, -1, 0, process_cb, arg); > event_add(&timer_ev, &delta_tv); > gettimeofday(&now, NULL); > timeradd(&now, &delta_tv, &next_wakeup_tv); > } > > > == > Ken > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users -- -Ken From joao.pascoaes at hotmail.com Sat Aug 11 19:27:41 2007 From: joao.pascoaes at hotmail.com (=?iso-8859-1?B?Sm/jbyBQYXNjb2Flcw==?=) Date: Sat Aug 11 19:27:52 2007 Subject: [Libevent-users] Segmentation fault - const struct eventop *evsel = base->evsel; Message-ID: Hello all, My problem is: I'm developping an application in C++ with libevent 1.3c (and g++ 4.0.3). My main function creates an object from a class A witch creates one object from class B. - In object from class A, I call event_init() and event_dispatch() functions (there are events related with sockets here, all working good); - In object from class B there is an event timer triggering each 50 seconds (tvTime); - "struct event evTime" and "struct timeval tvTime" are declared in class B; - "evtimer_set(&evTime, func, (void *) this)" and "evtimer_add(&evTime)" present in class B; >From time to time, object from class B is deleted. Problem: After that, when object from class A creates another object from class B: - "evtimer_initialized(&evTime)" returns true (how?), followed by "evtimer_del(&evTime)" (working!) and after by "evtimer_add(&evTime)". However, "evtimer_add(&evTime)" raises a segmentation default: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1212361024 (LWP 8533)] event_add (ev=0x80a39c0, tv=0x80a3a14) at event.c:622 622 const struct eventop *evsel = base->evsel; What am I dowing wrong? Can you help me, please? Thanks :) Jo?o _________________________________________________________________ Transfira J? a ?ltima vers?o do Windows Live Messenger! http://get.live.com/pt-pt/messenger/overview From charles at rebelbase.com Mon Aug 13 23:55:04 2007 From: charles at rebelbase.com (Charles Kerr) Date: Tue Aug 14 01:16:38 2007 Subject: [Libevent-users] [patch] 1.3c bug in evhttp_add_header() Message-ID: <46C12798.3020500@rebelbase.com> 1.3c's evhttp_add_header() function has a pretty nasty bug that can cause valid headers to be rejected out of hand, and also can cause parsing of incoming messages to fail. The problem is that strchr() is being passed two strings, rather than a string and a character. --- http.c.bak 2007-08-13 22:51:30.000000000 -0500 +++ http.c 2007-08-13 22:51:44.000000000 -0500 @@ -1122,7 +1122,7 @@ { struct evkeyval *header; - if (strchr(value, "\r") != NULL || strchr(value, "\n") != NULL) { + if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL) { /* drop illegal headers */ return (-1); } cheers, Charles From provos at citi.umich.edu Tue Aug 14 09:13:47 2007 From: provos at citi.umich.edu (Niels Provos) Date: Tue Aug 14 09:14:01 2007 Subject: [Libevent-users] [patch] 1.3c bug in evhttp_add_header() In-Reply-To: <46C12798.3020500@rebelbase.com> References: <46C12798.3020500@rebelbase.com> Message-ID: <850f7cbe0708140613r9612d5ckdd7dbb73cd08b822@mail.gmail.com> This has been fixed in trunk already. There is going to be a new release soon - I have been traveling for the last week. This was a pretty dumb bug and shows why unittesting is really important. Niels. On 8/13/07, Charles Kerr wrote: > 1.3c's evhttp_add_header() function has a pretty nasty bug that > can cause valid headers to be rejected out of hand, and also can > cause parsing of incoming messages to fail. The problem is > that strchr() is being passed two strings, rather than a string > and a character. > > --- http.c.bak 2007-08-13 22:51:30.000000000 -0500 > +++ http.c 2007-08-13 22:51:44.000000000 -0500 > @@ -1122,7 +1122,7 @@ > { > struct evkeyval *header; > > - if (strchr(value, "\r") != NULL || strchr(value, "\n") != NULL) { > + if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL) { > /* drop illegal headers */ > return (-1); > } > > cheers, > Charles > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > From provos at citi.umich.edu Thu Aug 16 01:01:29 2007 From: provos at citi.umich.edu (Niels Provos) Date: Thu Aug 16 01:01:32 2007 Subject: [Libevent-users] [patch] 1.3c bug in evhttp_add_header() In-Reply-To: <850f7cbe0708140613r9612d5ckdd7dbb73cd08b822@mail.gmail.com> References: <46C12798.3020500@rebelbase.com> <850f7cbe0708140613r9612d5ckdd7dbb73cd08b822@mail.gmail.com> Message-ID: <850f7cbe0708152201n9ad2a3w98a69e4ccc4523c1@mail.gmail.com> I just released 1.3d which fixes this and one other bug. Niels. On 8/14/07, Niels Provos wrote: > This has been fixed in trunk already. There is going to be a new > release soon - I have been traveling for the last week. This was a > pretty dumb bug and shows why unittesting is really important. > > Niels. > > On 8/13/07, Charles Kerr wrote: > > 1.3c's evhttp_add_header() function has a pretty nasty bug that > > can cause valid headers to be rejected out of hand, and also can > > cause parsing of incoming messages to fail. The problem is > > that strchr() is being passed two strings, rather than a string > > and a character. > > > > --- http.c.bak 2007-08-13 22:51:30.000000000 -0500 > > +++ http.c 2007-08-13 22:51:44.000000000 -0500 > > @@ -1122,7 +1122,7 @@ > > { > > struct evkeyval *header; > > > > - if (strchr(value, "\r") != NULL || strchr(value, "\n") != NULL) { > > + if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL) { > > /* drop illegal headers */ > > return (-1); > > } > > > > cheers, > > Charles > > _______________________________________________ > > Libevent-users mailing list > > Libevent-users@monkey.org > > http://monkey.org/mailman/listinfo/libevent-users > > > > > From ralmoritz at gmail.com Fri Aug 17 03:51:09 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Fri Aug 17 03:51:12 2007 Subject: [Libevent-users] gcc complains about TAILQ_ENTRY Message-ID: Hi, when I try to compile libevent, gcc exits with an error. Sorry I don't remember the exact error message, but it occurs in evhttp:109, which is: TAILQ_ENTRY(evhttp_request) next; I have to replace this with: struct { struct evhttp_request *tqe_next; /* next element */ struct evhttp_request **tqe_prev; /* address of previous next element */ } next; to get it to compile. It's odd because that's what the macro should expand to anyway. I'm using gcc 4.1 on Linux. -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From wouter at nlnetlabs.nl Fri Aug 17 04:37:26 2007 From: wouter at nlnetlabs.nl (W.C.A. Wijngaards) Date: Fri Aug 17 05:00:31 2007 Subject: [Libevent-users] gcc complains about TAILQ_ENTRY In-Reply-To: References: Message-ID: <46C55E46.9010902@nlnetlabs.nl> Hi Ralph, With gcc 4.1.2 on linux, I get no error messages at all. This is for a compile of the libevent trunk. Perhaps the error message is useful after all - and may I suggest looking at the ./configure detection output for since it tries to detect sys/queue.h for that TAILQ stuff in there. Best regards, Wouter Ralph Moritz wrote: > Hi, > > when I try to compile libevent, gcc exits with an error. Sorry I don't > remember the exact error message, but it occurs in evhttp:109, which > is: > > TAILQ_ENTRY(evhttp_request) next; > > I have to replace this with: > > struct { > struct evhttp_request *tqe_next; /* next element */ > struct evhttp_request **tqe_prev; /* address of previous next element */ > } next; > > to get it to compile. It's odd because that's what the macro should > expand to anyway. I'm using gcc 4.1 on Linux. > > From ralmoritz at gmail.com Fri Aug 17 05:20:49 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Fri Aug 17 05:20:52 2007 Subject: [Libevent-users] gcc complains about TAILQ_ENTRY In-Reply-To: <46C55E46.9010902@nlnetlabs.nl> References: <46C55E46.9010902@nlnetlabs.nl> Message-ID: Hi Wouter, I'll compile again tonight and save the output of ./configure and make. On 17/08/07, W.C.A. Wijngaards wrote: [snip] > Perhaps the error message is useful after all - and may I suggest > looking at the ./configure detection output for since it tries to detect > sys/queue.h for that TAILQ stuff in there. > > Best regards, > Wouter > > Ralph Moritz wrote: > > Hi, > > > > when I try to compile libevent, gcc exits with an error. Sorry I don't > > remember the exact error message, but it occurs in evhttp:109, which > > is: > > > > TAILQ_ENTRY(evhttp_request) next; > > > > I have to replace this with: > > > > struct { > > struct evhttp_request *tqe_next; /* next element */ > > struct evhttp_request **tqe_prev; /* address of previous next element */ > > } next; > > > > to get it to compile. It's odd because that's what the macro should > > expand to anyway. I'm using gcc 4.1 on Linux. -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From kelly at slackwarelinux.kicks-ass.net Sun Aug 19 19:17:42 2007 From: kelly at slackwarelinux.kicks-ass.net (Kelly Anderson) Date: Sun Aug 19 19:44:42 2007 Subject: [Libevent-users] libevent 1.3b VPATH fix Message-ID: <46C8CF96.1000600@slackwarelinux.kicks-ass.net> Hello, I've attached a shell script which will fix some paths in the Makefile.am's. This will allow VPATH to work so that you can build out of the source tree. It's not an obtrusive change (usually doesn't take much to fix them). It's kinda handy when you're building for multiple architectures. You don't have to "make clean", just delete your build dir when your done. cd builddir ../pathtosource/configure make Thanks! -------------- next part -------------- #! /bin/bash libeventVPATHPatcher() { # Fix paths that break VPATH if [[ ! -f 'Makefile.am.orig' ]]; then cp -p 'Makefile.am' 'Makefile.am.orig' ed 'Makefile.am' < References: <46C8CF96.1000600@slackwarelinux.kicks-ass.net> Message-ID: <850f7cbe0708191849q200fed53pbf9667cb2bb3b4b7@mail.gmail.com> Why don't you send a patch? The shell script does not patch trunk correctly. Niels. On 8/19/07, Kelly Anderson wrote: > Hello, > > I've attached a shell script which will fix some paths in the > Makefile.am's. This will allow VPATH to work so that you can build out > of the source tree. It's not an obtrusive change (usually doesn't take > much to fix them). It's kinda handy when you're building for multiple > architectures. You don't have to "make clean", just delete your build > dir when your done. > > cd builddir > ../pathtosource/configure > make > > Thanks! > > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > > From kelly at slackwarelinux.kicks-ass.net Sun Aug 19 22:07:17 2007 From: kelly at slackwarelinux.kicks-ass.net (Kelly Anderson) Date: Sun Aug 19 22:07:43 2007 Subject: [Libevent-users] libevent 1.3b VPATH fix In-Reply-To: <850f7cbe0708191849q200fed53pbf9667cb2bb3b4b7@mail.gmail.com> References: <46C8CF96.1000600@slackwarelinux.kicks-ass.net> <850f7cbe0708191849q200fed53pbf9667cb2bb3b4b7@mail.gmail.com> Message-ID: <46C8F755.2000307@slackwarelinux.kicks-ass.net> Niels Provos wrote: > Why don't you send a patch? The shell script does not patch trunk correctly. > > Niels. > > On 8/19/07, Kelly Anderson wrote: > >> Hello, >> >> I've attached a shell script which will fix some paths in the >> Makefile.am's. This will allow VPATH to work so that you can build out >> of the source tree. It's not an obtrusive change (usually doesn't take >> much to fix them). It's kinda handy when you're building for multiple >> architectures. You don't have to "make clean", just delete your build >> dir when your done. >> >> cd builddir >> ../pathtosource/configure >> make >> >> Thanks! >> >> _______________________________________________ >> Libevent-users mailing list >> Libevent-users@monkey.org >> http://monkey.org/mailman/listinfo/libevent-users >> >> >> >> Here you go. Thanks again. -------------- next part -------------- *** ./Makefile.am.orig 2007-03-03 21:06:06.000000000 -0700 --- ./Makefile.am 2007-08-19 16:37:10.784700560 -0600 *************** *** 47,57 **** include_HEADERS = event.h evhttp.h evdns.h ! INCLUDES = -Icompat $(SYS_INCLUDES) man_MANS = event.3 evdns.3 verify: libevent.la ! cd $(srcdir)/test && make verify DISTCLEANFILES = *~ --- 47,57 ---- include_HEADERS = event.h evhttp.h evdns.h ! INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES) man_MANS = event.3 evdns.3 verify: libevent.la ! cd test && make verify DISTCLEANFILES = *~ *** ./sample/Makefile.am.orig 2007-02-15 17:48:32.000000000 -0700 --- ./sample/Makefile.am 2007-08-19 16:37:10.784700560 -0600 *************** *** 1,8 **** AUTOMAKE_OPTIONS = foreign no-dependencies LDADD = ../libevent.la ! CPPFPLAGS = -I.. ! CFLAGS = -I../compat noinst_PROGRAMS = event-test time-test signal-test --- 1,8 ---- AUTOMAKE_OPTIONS = foreign no-dependencies LDADD = ../libevent.la ! CPPFLAGS = -I$(top_srcdir) ! CFLAGS = -I$(top_srcdir)/compat noinst_PROGRAMS = event-test time-test signal-test *** ./test/Makefile.am.orig 2007-02-15 17:48:32.000000000 -0700 --- ./test/Makefile.am 2007-08-19 16:37:10.784700560 -0600 *************** *** 1,8 **** AUTOMAKE_OPTIONS = foreign no-dependencies LDADD = ../libevent.la ! CPPFPLAGS = -I.. ! CFLAGS = -I../compat @CFLAGS@ EXTRA_DIST = regress.rpc --- 1,8 ---- AUTOMAKE_OPTIONS = foreign no-dependencies LDADD = ../libevent.la ! CPPFLAGS = -I$(top_srcdir) ! CFLAGS = -I$(top_srcdir)/compat EXTRA_DIST = regress.rpc *************** *** 18,24 **** bench_SOURCES = bench.c regress.gen.c regress.gen.h: regress.rpc ! ../event_rpcgen.py regress.rpc || echo "No Python installed" DISTCLEANFILES = *~ CLEANFILES = regress.gen.h regress.gen.c --- 18,24 ---- bench_SOURCES = bench.c regress.gen.c regress.gen.h: regress.rpc ! $(top_srcdir)/event_rpcgen.py regress.rpc || echo "No Python installed" DISTCLEANFILES = *~ CLEANFILES = regress.gen.h regress.gen.c From nickm at freehaven.net Mon Aug 20 10:45:14 2007 From: nickm at freehaven.net (Nick Mathewson) Date: Mon Aug 20 10:45:17 2007 Subject: [Libevent-users] libevent 1.3b VPATH fix In-Reply-To: <46C8F755.2000307@slackwarelinux.kicks-ass.net> References: <46C8CF96.1000600@slackwarelinux.kicks-ass.net> <850f7cbe0708191849q200fed53pbf9667cb2bb3b4b7@mail.gmail.com> <46C8F755.2000307@slackwarelinux.kicks-ass.net> Message-ID: <20070820144514.GG21346@totoro.wangafu.net> On Sun, Aug 19, 2007 at 08:07:17PM -0600, Kelly Anderson wrote: [...] > Here you go. Thanks again. Hi! It still didn't apply cleanly to trunk, but I managed to clean it up and check it in anyway. Could you take a look at your convenience and let us know whether it was what you had in mind? cheers, -- Nick Mathewson -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 652 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070820/560b3353/attachment.bin From charles at rebelbase.com Mon Aug 20 16:19:28 2007 From: charles at rebelbase.com (Charles Kerr) Date: Mon Aug 20 16:16:56 2007 Subject: [Libevent-users] [patch] parse noncompliant http headers Message-ID: <46C9F750.1040102@rebelbase.com> I've been adapting the bittorrent client Transmission to use libevent as its IO backend. Unfortunately some of my users have reported that their trackers send noncompliant HTTP responses w.r.t using "\n" instead of "\r\n" as a line break. svn r400's evhttp_parse_lines() can't handle this, which causes libevent's http response parsing to fail. Attached is a patch to r400's evhttp_parse_lines() to handle nonstandard linebreaks gracefully by using evbuffer_readline(). Charles -------------- next part -------------- A non-text attachment was scrubbed... Name: http.patch Type: text/x-patch Size: 1860 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070820/585f04a9/http.bin From ralmoritz at gmail.com Wed Aug 22 12:51:12 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Wed Aug 22 12:51:17 2007 Subject: [Libevent-users] No Date header in HTTP/1.1 response Message-ID: Hi, according to RFC 2616: Origin servers MUST include a Date header field in all responses, except in these cases: 1. If the response status code is 100 (Continue) or 101 (Switching Protocols), the response MAY include a Date header field, at the server's option. 2. If the response status code conveys a server error, e.g. 500 (Internal Server Error) or 503 (Service Unavailable), and it is inconvenient or impossible to generate a valid Date. 3. If the server does not have a clock that can provide a reasonable approximation of the current time, its responses MUST NOT include a Date header field. In this case, the rules in section 14.18.1 MUST be followed. So I've modified `evhttp_make_header_response' appropriately. Patch below: --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 +++ http.c 2007-08-22 18:48:42.000000000 +0200 @@ -366,6 +366,25 @@ evhttp_make_header_response(struct evhtt evhttp_add_header(req->output_headers, "Content-Length", len); } + + /* + * Add required Date header to HTTP/1.1 responses. + * (Except those with status 100/1) + */ + if ((req->major == 1) + && (req->minor == 1) + && (req->response_code != 100) + && (req->response_code != 101)) { + static char date[50]; + static struct tm cur; + time_t t = time(NULL); + + gmtime_r(&t, &cur); + strftime(date, sizeof(date), + "%a, %d %b %Y %H:%M:%S GMT", &cur); + evhttp_add_header(req->output_headers, + "Date", date); + } } /* if the request asked for a close, we send a close, too */ -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From ralmoritz at gmail.com Wed Aug 22 14:55:14 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Wed Aug 22 14:55:18 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> Message-ID: Good point.After submitting this,I also realized that I forgot to check the return value of strftime(). On 8/22/07, Chris Ross wrote: > > If you're building a Date header anyway, why not go ahead and do > it in the case of 100 and 101, as well? It says it's permitted, > simply not required, so I don't see any significant value in special- > casing those two response codes... > > - Chris > > On Aug 22, 2007, at 12:51, Ralph Moritz wrote: > > Hi, > > > > according to RFC 2616: > > > > Origin servers MUST include a Date header field in all responses, > > except in these cases: > > > > 1. If the response status code is 100 (Continue) or 101 > > (Switching > > Protocols), the response MAY include a Date header field, at > > the server's option. > > > > 2. If the response status code conveys a server error, e.g. 500 > > (Internal Server Error) or 503 (Service Unavailable), and > > it is > > inconvenient or impossible to generate a valid Date. > > > > 3. If the server does not have a clock that can provide a > > reasonable approximation of the current time, its responses > > MUST NOT include a Date header field. In this case, the rules > > in section 14.18.1 MUST be followed. > > > > So I've modified `evhttp_make_header_response' appropriately. Patch > > below: > > > > --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 > > +++ http.c 2007-08-22 18:48:42.000000000 +0200 > > @@ -366,6 +366,25 @@ evhttp_make_header_response(struct evhtt > > evhttp_add_header(req->output_headers, > > "Content-Length", len); > > } > > + > > + /* > > + * Add required Date header to HTTP/1.1 responses. > > + * (Except those with status 100/1) > > + */ > > + if ((req->major == 1) > > + && (req->minor == 1) > > + && (req->response_code != 100) > > + && (req->response_code != 101)) { > > + static char date[50]; > > + static struct tm cur; > > + time_t t = time(NULL); > > + > > + gmtime_r(&t, &cur); > > + strftime(date, sizeof(date), > > + "%a, %d %b %Y %H:%M:%S GMT", &cur); > > + evhttp_add_header(req->output_headers, > > + "Date", date); > > + } > > } > > > > /* if the request asked for a close, we send a close, too */ > > > > > > -- > > Ralph Moritz > > Ph: +27 84 626 9070 > > GPG Public Key: http://ralphm.info/public.gpg > > _______________________________________________ > > Libevent-users mailing list > > Libevent-users@monkey.org > > http://monkey.org/mailman/listinfo/libevent-users > > -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From acd at weirdness.net Wed Aug 22 15:03:34 2007 From: acd at weirdness.net (Andrew Danforth) Date: Wed Aug 22 15:03:39 2007 Subject: [Libevent-users] No Date header in HTTP/1.1 response In-Reply-To: References: Message-ID: Any particular reason why you made date and cur static? Seems like there's little benefit in doing so and you're potentially introducing bugs in threaded apps if they use the evhttp stuff concurrently. A On 8/22/07, Ralph Moritz wrote: > > Hi, > > according to RFC 2616: > > Origin servers MUST include a Date header field in all responses, > except in these cases: > > 1. If the response status code is 100 (Continue) or 101 (Switching > Protocols), the response MAY include a Date header field, at > the server's option. > > 2. If the response status code conveys a server error, e.g. 500 > (Internal Server Error) or 503 (Service Unavailable), and it is > inconvenient or impossible to generate a valid Date. > > 3. If the server does not have a clock that can provide a > reasonable approximation of the current time, its responses > MUST NOT include a Date header field. In this case, the rules > in section 14.18.1 MUST be followed. > > So I've modified `evhttp_make_header_response' appropriately. Patch below: > > --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 > +++ http.c 2007-08-22 18:48:42.000000000 +0200 > @@ -366,6 +366,25 @@ evhttp_make_header_response(struct evhtt > evhttp_add_header(req->output_headers, > "Content-Length", len); > } > + > + /* > + * Add required Date header to HTTP/1.1 responses. > + * (Except those with status 100/1) > + */ > + if ((req->major == 1) > + && (req->minor == 1) > + && (req->response_code != 100) > + && (req->response_code != 101)) { > + static char date[50]; > + static struct tm cur; > + time_t t = time(NULL); > + > + gmtime_r(&t, &cur); > + strftime(date, sizeof(date), > + "%a, %d %b %Y %H:%M:%S GMT", &cur); > + evhttp_add_header(req->output_headers, > + "Date", date); > + } > } > > /* if the request asked for a close, we send a close, too */ > > > -- > Ralph Moritz > Ph: +27 84 626 9070 > GPG Public Key: http://ralphm.info/public.gpg > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://monkeymail.org/archives/libevent-users/attachments/20070822/ccb2d9ab/attachment.htm From elliotf-libevent at gratuitous.net Wed Aug 22 15:27:16 2007 From: elliotf-libevent at gratuitous.net (Elliot Foster) Date: Wed Aug 22 15:27:18 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> Message-ID: <46CC8E14.8050007@gratuitous.net> Ralph Moritz wrote: > Good point.After submitting this,I also realized that I forgot to > check the return value of strftime(). For that matter, why limit it to 1.1? 1.0 allows the Date header as well (RFC1945, 10.6). Also, thank you for adding this. > On 8/22/07, Chris Ross wrote: >> If you're building a Date header anyway, why not go ahead and do >> it in the case of 100 and 101, as well? It says it's permitted, >> simply not required, so I don't see any significant value in special- >> casing those two response codes... >> >> - Chris >> >> On Aug 22, 2007, at 12:51, Ralph Moritz wrote: >>> Hi, >>> >>> according to RFC 2616: >>> >>> Origin servers MUST include a Date header field in all responses, >>> except in these cases: >>> >>> 1. If the response status code is 100 (Continue) or 101 >>> (Switching >>> Protocols), the response MAY include a Date header field, at >>> the server's option. >>> >>> 2. If the response status code conveys a server error, e.g. 500 >>> (Internal Server Error) or 503 (Service Unavailable), and >>> it is >>> inconvenient or impossible to generate a valid Date. >>> >>> 3. If the server does not have a clock that can provide a >>> reasonable approximation of the current time, its responses >>> MUST NOT include a Date header field. In this case, the rules >>> in section 14.18.1 MUST be followed. >>> >>> So I've modified `evhttp_make_header_response' appropriately. Patch >>> below: >>> >>> --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 >>> +++ http.c 2007-08-22 18:48:42.000000000 +0200 >>> @@ -366,6 +366,25 @@ evhttp_make_header_response(struct evhtt >>> evhttp_add_header(req->output_headers, >>> "Content-Length", len); >>> } >>> + >>> + /* >>> + * Add required Date header to HTTP/1.1 responses. >>> + * (Except those with status 100/1) >>> + */ >>> + if ((req->major == 1) >>> + && (req->minor == 1) >>> + && (req->response_code != 100) >>> + && (req->response_code != 101)) { >>> + static char date[50]; >>> + static struct tm cur; >>> + time_t t = time(NULL); >>> + >>> + gmtime_r(&t, &cur); >>> + strftime(date, sizeof(date), >>> + "%a, %d %b %Y %H:%M:%S GMT", &cur); >>> + evhttp_add_header(req->output_headers, >>> + "Date", date); >>> + } >>> } >>> >>> /* if the request asked for a close, we send a close, too */ >>> >>> >>> -- >>> Ralph Moritz >>> Ph: +27 84 626 9070 >>> GPG Public Key: http://ralphm.info/public.gpg >>> _______________________________________________ >>> Libevent-users mailing list >>> Libevent-users@monkey.org >>> http://monkey.org/mailman/listinfo/libevent-users >> > > From ralmoritz at gmail.com Thu Aug 23 03:15:45 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Thu Aug 23 03:15:53 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: <46CC89F3.6080809@gratuitous.net> References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> <46CC89F3.6080809@gratuitous.net> Message-ID: On 22/08/07, Elliot Foster wrote: > Ralph Moritz wrote: > > Good point.After submitting this,I also realized that I forgot to > > check the return value of strftime(). > > For that matter, why limit it to 1.1? 1.0 allows the Date header as well > (RFC1945, 10.6). Also, thank you for adding this. Modified patch below: --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 +++ http.c 2007-08-23 09:11:50.000000000 +0200 @@ -366,6 +366,20 @@ evhttp_make_header_response(struct evhtt evhttp_add_header(req->output_headers, "Content-Length", len); } + + /* Add Date header. (Required by HTTP/1.1) */ + char date[50]; + struct tm cur; + time_t t = time(NULL); + int l; + + gmtime_r(&t, &cur); + l = strftime(date, sizeof(date), + "%a, %d %b %Y %H:%M:%S GMT", &cur); + if (l != 0) { + evhttp_add_header(req->output_headers, + "Date", date); + } } /* if the request asked for a close, we send a close, too */ -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From ralmoritz at gmail.com Thu Aug 23 03:18:41 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Thu Aug 23 03:18:45 2007 Subject: [Libevent-users] Conditional include for time.h Message-ID: Hi, I've noticed that http.c conditionally includes time.h. I'm wondering why since time.h is part of C89, so AFAIK it should always be present. -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From jan at kneschke.de Thu Aug 23 05:28:20 2007 From: jan at kneschke.de (Jan Kneschke) Date: Thu Aug 23 05:28:27 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> <46CC89F3.6080809@gratuitous.net> Message-ID: <46CD5334.8090307@kneschke.de> Ralph Moritz wrote: > On 22/08/07, Elliot Foster wrote: >> Ralph Moritz wrote: >>> Good point.After submitting this,I also realized that I forgot to >>> check the return value of strftime(). >> For that matter, why limit it to 1.1? 1.0 allows the Date header as well >> (RFC1945, 10.6). Also, thank you for adding this. > > Modified patch below: > > --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 > +++ http.c 2007-08-23 09:11:50.000000000 +0200 > @@ -366,6 +366,20 @@ evhttp_make_header_response(struct evhtt > evhttp_add_header(req->output_headers, > "Content-Length", len); > } > + > + /* Add Date header. (Required by HTTP/1.1) */ > + char date[50]; > + struct tm cur; > + time_t t = time(NULL); > + int l; > + > + gmtime_r(&t, &cur); > + l = strftime(date, sizeof(date), > + "%a, %d %b %Y %H:%M:%S GMT", &cur); > + if (l != 0) { > + evhttp_add_header(req->output_headers, > + "Date", date); > + } > } > > /* if the request asked for a close, we send a close, too */ > This patch will break on non C99 compilers with mixed declaration/code errors. Please move the declarations up to the start of this block. cheers, Jan -- jan: "Gee, Brain^WEric, what'd you wanna do tonight?" eric: Same thing we do everynight: Take over the HelloWorld! From ralmoritz at gmail.com Thu Aug 23 06:14:09 2007 From: ralmoritz at gmail.com (Ralph Moritz) Date: Thu Aug 23 06:14:12 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: <46CD5334.8090307@kneschke.de> References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> <46CC89F3.6080809@gratuitous.net> <46CD5334.8090307@kneschke.de> Message-ID: On 23/08/07, Jan Kneschke wrote: > This patch will break on non C99 compilers with mixed declaration/code > errors. Please move the declarations up to the start of this block. Thanks for spotting that. New patch below. Hopefully this one's kosher. --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 +++ http.c 2007-08-23 12:11:50.000000000 +0200 @@ -345,6 +345,20 @@ evhttp_make_header_response(struct evhtt /* Potentially add headers for unidentified content. */ if (EVBUFFER_LENGTH(req->output_buffer)) { + /* Add Date header. (Required by HTTP/1.1) */ + char date[50]; + struct tm cur; + time_t t = time(NULL); + int l; + + gmtime_r(&t, &cur); + l = strftime(date, sizeof(date), + "%a, %d %b %Y %H:%M:%S GMT", &cur); + if (l != 0) { + evhttp_add_header(req->output_headers, + "Date", date); + } + if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) { evhttp_add_header(req->output_headers, -- Ralph Moritz Ph: +27 84 626 9070 GPG Public Key: http://ralphm.info/public.gpg From charles at rebelbase.com Thu Aug 23 11:39:33 2007 From: charles at rebelbase.com (Charles Kerr) Date: Thu Aug 23 12:00:38 2007 Subject: [Libevent-users] [patch] evhttp.h portability + http parsing noncompliant headers Message-ID: <33700.129.15.110.8.1187883573.squirrel@webmail.rebelbase.com> Attached is a two-part patch. First, it makes evhttp.h portable on mingw and other systems w/o TAILQ_ENTRY by defining the macro itself if a system header hasn't already defined it. This is the same as what event.h already does. The second part is a repeat of the patch I submitted a couple of days ago that lets libevent's http parser more gracefully handle servers that don't use the proper \r\n linebreak. Some tracker servers only return \n, which breaks the current libevent's parsing. Those servers are causing me quite a headache, but there was no response to my initial patch. Is this something that's likely to be considered for use in libevent? Charles -------------- next part -------------- A non-text attachment was scrubbed... Name: libevent.patch Type: text/x-patch Size: 3090 bytes Desc: not available Url : http://monkeymail.org/archives/libevent-users/attachments/20070823/474ef8ed/libevent.bin From Bob.Maccione at hilton.com Fri Aug 24 00:34:48 2007 From: Bob.Maccione at hilton.com (Bob Maccione) Date: Fri Aug 24 00:53:42 2007 Subject: [Libevent-users] running as a forked process errors out Message-ID: <88CD683992DCAF4C9D443DF8CA005D66030B613E@hwmxmsg03.hotels.ad.hilton.com> I have a simple app that I tried to convert to run as a daemon. This is on Solaris and when i do the fork() I get the following error from the event_dispatch() ioctl: DP_POLL: Permission denied event_dispatch received an error of -1 I'm wondering if anyone has seen this before or has working daemon code that they would be willing to share.. I've tried the following if( fork() ) { exit(0); } setsid(); if( fork() ) { exit(0); } then do the rest of the code.... the 2 forks are recommended in all of the popular texts (i.e. Stevens )... thanks for any help, bobm -------------- next part -------------- An HTML attachment was scrubbed... URL: http://monkeymail.org/archives/libevent-users/attachments/20070823/acd467e6/attachment.htm From acd at weirdness.net Fri Aug 24 10:27:21 2007 From: acd at weirdness.net (Andrew Danforth) Date: Fri Aug 24 10:28:40 2007 Subject: [Libevent-users] running as a forked process errors out In-Reply-To: <88CD683992DCAF4C9D443DF8CA005D66030B613E@hwmxmsg03.hotels.ad.hilton.com> References: <88CD683992DCAF4C9D443DF8CA005D66030B613E@hwmxmsg03.hotels.ad.hilton.com> Message-ID: You need do all your forking before you call event_init. libevent on Solaris uses /dev/poll, and /dev/poll doesn't support children inheriting a parent's /dev/poll file descriptor. >From poll(7d): The /dev/poll driver caches a list of polled file descrip- tors, which are specific to a process. Therefore, the /dev/poll file descriptor of a process will be inherited by its child process, just like any other file descriptors. But the child process will have very limited access through this inherited /dev/poll file descriptor. Any attempt to write or do ioctl by the child process will result in an EACCES error. The child process should close the inherited /dev/poll file descriptor and open its own if desired. Andrew On 8/24/07, Bob Maccione wrote: > I have a simple app that I tried to convert to run as a daemon. > > This is on Solaris and when i do the fork() I get the following error from > the event_dispatch() > > ioctl: DP_POLL: Permission denied > event_dispatch received an error of -1 > > I'm wondering if anyone has seen this before or has working daemon code > that they would be willing to share.. > > I've tried the following > > if( fork() ) { > exit(0); > } > > setsid(); > > if( fork() ) { > exit(0); > } > > then do the rest of the code.... > > the 2 forks are recommended in all of the popular texts (i.e. Stevens > )... > > thanks for any help, > bobm > > > > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://monkeymail.org/archives/libevent-users/attachments/20070824/86fd5a6b/attachment.htm From provos at citi.umich.edu Fri Aug 24 10:38:16 2007 From: provos at citi.umich.edu (Niels Provos) Date: Fri Aug 24 10:38:18 2007 Subject: [Libevent-users] [patch] evhttp.h portability + http parsing noncompliant headers In-Reply-To: <33700.129.15.110.8.1187883573.squirrel@webmail.rebelbase.com> References: <33700.129.15.110.8.1187883573.squirrel@webmail.rebelbase.com> Message-ID: <850f7cbe0708240738s72c31dcbv86b06d93ffe92190@mail.gmail.com> Hi Charles, thanks for your patches. We are going to integrate them in some form into a trunk - I'll probably have to massage them a little bit. Niels. On 8/23/07, Charles Kerr wrote: > Attached is a two-part patch. First, it makes evhttp.h portable on > mingw and other systems w/o TAILQ_ENTRY by defining the macro itself > if a system header hasn't already defined it. This is the same as > what event.h already does. > > The second part is a repeat of the patch I submitted a couple of days > ago that lets libevent's http parser more gracefully handle servers > that don't use the proper \r\n linebreak. Some tracker servers only > return \n, which breaks the current libevent's parsing. > > Those servers are causing me quite a headache, but there was no > response to my initial patch. Is this something that's likely to > be considered for use in libevent? > > Charles > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > > From provos at citi.umich.edu Sat Aug 25 14:48:23 2007 From: provos at citi.umich.edu (Niels Provos) Date: Sat Aug 25 14:48:26 2007 Subject: [Libevent-users] [patch] evhttp.h portability + http parsing noncompliant headers In-Reply-To: <850f7cbe0708240738s72c31dcbv86b06d93ffe92190@mail.gmail.com> References: <33700.129.15.110.8.1187883573.squirrel@webmail.rebelbase.com> <850f7cbe0708240738s72c31dcbv86b06d93ffe92190@mail.gmail.com> Message-ID: <850f7cbe0708251148i5cb98ef7wcf0759976243d90f@mail.gmail.com> Hi Charles, I submitted the header parsing changes to trunk. They look fine, but they probably need some exposure before we are completely comfortable with them. Thank you, Niels. On 8/24/07, Niels Provos wrote: > Hi Charles, > > thanks for your patches. We are going to integrate them in some form > into a trunk - I'll probably have to massage them a little bit. > > Niels. > > On 8/23/07, Charles Kerr wrote: > > Attached is a two-part patch. First, it makes evhttp.h portable on > > mingw and other systems w/o TAILQ_ENTRY by defining the macro itself > > if a system header hasn't already defined it. This is the same as > > what event.h already does. > > > > The second part is a repeat of the patch I submitted a couple of days > > ago that lets libevent's http parser more gracefully handle servers > > that don't use the proper \r\n linebreak. Some tracker servers only > > return \n, which breaks the current libevent's parsing. > > > > Those servers are causing me quite a headache, but there was no > > response to my initial patch. Is this something that's likely to > > be considered for use in libevent? > > > > Charles > > _______________________________________________ > > Libevent-users mailing list > > Libevent-users@monkey.org > > http://monkey.org/mailman/listinfo/libevent-users > > > > > > > From provos at citi.umich.edu Sun Aug 26 21:24:25 2007 From: provos at citi.umich.edu (Niels Provos) Date: Sun Aug 26 21:24:30 2007 Subject: [Libevent-users] Re: No Date header in HTTP/1.1 response In-Reply-To: References: <033F81DE-9BF0-4523-8C5F-88827430F891@distal.com> <46CC89F3.6080809@gratuitous.net> <46CD5334.8090307@kneschke.de> Message-ID: <850f7cbe0708261824m3c947922tac04d2392484fec0@mail.gmail.com> And you also need to check if there is a Date header already. You don't want it to appear twice. Niels. On 8/23/07, Ralph Moritz wrote: > On 23/08/07, Jan Kneschke wrote: > > This patch will break on non C99 compilers with mixed declaration/code > > errors. Please move the declarations up to the start of this block. > > Thanks for spotting that. New patch below. Hopefully this one's kosher. > > --- http.c.bak 2007-08-16 06:50:57.000000000 +0200 > +++ http.c 2007-08-23 12:11:50.000000000 +0200 > @@ -345,6 +345,20 @@ evhttp_make_header_response(struct evhtt > > /* Potentially add headers for unidentified content. */ > if (EVBUFFER_LENGTH(req->output_buffer)) { > + /* Add Date header. (Required by HTTP/1.1) */ > + char date[50]; > + struct tm cur; > + time_t t = time(NULL); > + int l; > + > + gmtime_r(&t, &cur); > + l = strftime(date, sizeof(date), > + "%a, %d %b %Y %H:%M:%S GMT", &cur); > + if (l != 0) { > + evhttp_add_header(req->output_headers, > + "Date", date); > + } > + > if (evhttp_find_header(req->output_headers, > "Content-Type") == NULL) { > evhttp_add_header(req->output_headers, > > > -- > Ralph Moritz > Ph: +27 84 626 9070 > GPG Public Key: http://ralphm.info/public.gpg > _______________________________________________ > Libevent-users mailing list > Libevent-users@monkey.org > http://monkey.org/mailman/listinfo/libevent-users > > From gmagic10 at gmail.com Tue Aug 28 03:41:29 2007 From: gmagic10 at gmail.com (Magic Jacky) Date: Tue Aug 28 03:41:40 2007 Subject: [Libevent-users] I can't compile libevent in Windows of VC6 Message-ID: Hi all I currently using libevent. I get the code from svn of sf.net. I CAN compile the libevent.lib. But when I try to compile the event_test project. I get the error as follow: libevent.lib(event.obj) : error LNK2001: unresolved external symbol _evsignal_base libevent.lib(event.obj) : error LNK2001: unresolved external symbol _timeradd libevent.lib(event.obj) : error LNK2001: unresolved external symbol _timersub libevent.lib(win32.obj) : error LNK2001: unresolved external symbol ___WSAFDIsSet@8 libevent.lib(win32.obj) : error LNK2001: unresolved external symbol _select@20 libevent.lib(win32.obj) : error LNK2001: unresolved external symbol _signalqueue Can anybody give me some hints? Thank you very much!! -------------- next part -------------- An HTML attachment was scrubbed... URL: http://monkeymail.org/archives/libevent-users/attachments/20070828/5fe41170/attachment.htm From blibbet at gmail.com Tue Aug 28 12:20:52 2007 From: blibbet at gmail.com (Lee Fisher) Date: Tue Aug 28 12:34:07 2007 Subject: [Libevent-users] I can't compile libevent in Windows of VC6 In-Reply-To: References: Message-ID: <46D44B64.4040902@gmail.com> The VC project files are outdated, libevent has more C source files now, which have never compiled with MSC yet. It is best to ignore the VS project files and stick with building via MinGW's GCC. Until one of us ports the rest of the source to MSC :-) > Can anybody give me some hints? Thank you very much!! > >