Re: [Libevent-users] HTTP proxy

2009-04-11 Thread Scott Lamb
On Tue, Apr 7, 2009 at 11:20 AM, Jeroen Habraken  wrote:
> I've been looking at SpyBye to write a libevent based HTTP proxy, but
> I have a hard time understanding the structure and would like to know
> if there is a simpler example around ?
>
> The HTTP server from libevent is working great, but the problem are
> the DNS lookups and using libevent as a HTTP client.

You're welcome to look at foxigniter:

http://www.slamb.org/projects/foxigniter/

It's a (neglected) work in progress, but you might find it helpful.

> ___
> Libevent-users mailing list
> Libevent-users@monkey.org
> http://monkeymail.org/mailman/listinfo/libevent-users
>



-- 
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] getting notification of an evhttp_request being freed unexpectedly

2008-08-17 Thread Scott Lamb

Jon Singler wrote:

Alex Evans wrote:

hello. I'm fairly new to libevent and especially evhttp, so I have a query
whose solution may just be 'dont use evhttp that way'... the summary is: how
can I know if an evhttp_request object is 'freed' behind my back, and avoid
using it after it's dead?

I'm writing a simple single threaded libevent based http server that
occasionally can't immediately respond to an incoming http request that has
been passed into a generic handler callback. instead it just saves the
evhttp_request pointer in my own list structure, and doesn't immediately
call evhttp_send_reply or equivalent. instead it falls back to the main
dispatch loop and lets other events happen.
some time later another event allows me to fill in a reply to the old
request, and so I call evhttp_send_reply on the stored request pointer.
my issue is, that looking at the http.c code there are a few ways that the
http_request I am storing a pointer to, could be freed. for example, if the
incoming connection to a server goes away, it deletes all the outstanding
requests. however my code won't get any notification that the connection or
requests have gone away, so I will merrily (later on) make use of the
request pointer after it's been freed.
what should I do? not use this pattern? use some callback mechanism I've
missed? worry less? or patch evhttp_request_free() to call an optional
callback?


I am just getting my feet wet with evhttp, but it seems to me that the
evhttp_connection_set_closecb would be useful. You can register a
callback so you're informed when a connection is closed, and you
should be able to tie that together with an outstanding request pretty
easily. That was what I was planning to do, at least.


I think that won't work at present. Receiving the connection close 
callback does not mean the request will fail. Look at this code in 
evhttp_connection_fail:


/* reset the connection */
evhttp_connection_reset(evcon); <- this calls the close cb

/* We are trying the next request that was queued on us */
if (TAILQ_FIRST(&evcon->requests) != NULL)
evhttp_connection_connect(evcon);



I know that Niels has written at least one HTTP proxy server with
evhttp (spybye), so he would presumably have faced this exact issue,
and I'd be surprised if his solution was to just live with things
exploding at random intervals.


At least when I last looked at SpyBye, I think it was more a proof of 
concept than a totally complete and robust proxy implementation. IIRC it 
didn't do keepalives, didn't stream responses (much less have any flow 
control), so it would be somewhat slow and its memory usage could grow 
arbitrarily large. A fine piece of work, but (as with so much software) 
there's still work that could be done on it.




In general, I'm finding the evhttp stuff to be really well designed.
I've already had a few instances where I was trying to figure out how
to handle some aspect of implementing an HTTP server with evhttp where
I eventually figured out that I didn't have to do anything to handle
it, because evhttp took care of it for me, so hopefully this
contingency has also already been thought of and dealt with.

The authorities seem to be away on holiday (I'm still waiting for a
response to my question about why libevent forbids HTTP clients from
using a Content-Encoding header), but perhaps when they return they
will enlighten us as to the proper strategies.


It's a nice library (or I wouldn't be using it), but I have found (and 
fixed) several bugs and limitations.




-Jon
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] getting notification of an evhttp_request being freed unexpectedly

2008-08-12 Thread Scott Lamb

Alex Evans wrote:

hello. I'm fairly new to libevent and especially evhttp, so I have a query 
whose solution may just be 'dont use evhttp that way'... the summary is: how 
can I know if an evhttp_request object is 'freed' behind my back, and avoid 
using it after it's dead?

I'm writing a simple single threaded libevent based http server that 
occasionally can't immediately respond to an incoming http request that has 
been passed into a generic handler callback. instead it just saves the 
evhttp_request pointer in my own list structure, and doesn't immediately call 
evhttp_send_reply or equivalent. instead it falls back to the main dispatch 
loop and lets other events happen.
some time later another event allows me to fill in a reply to the old request, 
and so I call evhttp_send_reply on the stored request pointer.
my issue is, that looking at the http.c code there are a few ways that the 
http_request I am storing a pointer to, could be freed. for example, if the 
incoming connection to a server goes away, it deletes all the outstanding 
requests. however my code won't get any notification that the connection or 
requests have gone away, so I will merrily (later on) make use of the request 
pointer after it's been freed.
what should I do? not use this pattern? use some callback mechanism I've 
missed? worry less? or patch evhttp_request_free() to call an optional callback?


(Oops; resending with the list cced)

I believe you are exactly right and that this is an evhttp bug/API 
design flaw.


I've been working (off and on) on code with the same problem. It's a 
proxy server which streams results from the upstream (to which it acts 
as a client) to the downstream (to which it acts as a server). Thus, it 
also can't immediately respond to the downstream's request and has this 
window in which it assumes the evhttp_requests will not go away. 
Sometimes they do, and it crashes or at least behaves oddly. (In 
fairness, I'm not 100% sure this happens without some of the patches 
I've been working on, but I think it would.)


My first thought was that evhttp should track whether calling code is 
using a particular request (e.g., either it was created by the caller 
for client requests or evhttp has called a callback but not received a 
completed response) and send a callback indicating error. I haven't 
implemented this, and definitely won't for at least a week. (I'm on 
vacation, and my code's inaccessible from here.)


Besides the usual reasons for the connection being closed, the evhttp 
server code incorrectly interprets it as a connection close when it 
receives a pipelined request. Depending on what clients you have, that 
might be one reason you're encountering errors.




any help or advice greatly appreciated. many thanks
Alex



Please consider the environment before printing this email :-)

This email and any files transmitted with it are confidential and intended 
solely for the use of the individual or entity to whom they are addressed.  If 
you have received this email in error please notify the sender immediately then 
delete this email.

Media Molecule Limited
Company Reg No 5665849
Registered in England.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Keep Alive and POST

2008-08-10 Thread Scott Lamb

Derek Gottfrid wrote:

I noticed an oddity and want to check and see if anybody else was
seeing the same issue.

 If I call a eventlib http server w/ GET and Keep Alive and then
follow it up with a POST on the same connection, then I see a 400 Bad
Request message returned.  If I just call the POST directly on the
first call it works fine since there is not Keep Alive in play.  How
robust is the keep alive support?  I will keep digging and can post
some sample code if it helps.  Sorry for such newbie questions.


I think the keepalive support is reasonably good by now, at least in 
trunk head. (What version are you using?)


I haven't tested that specific case, though, and I suspect no one else 
has either. I deliberately avoid reusing connections for POST requests 
when issuing requests, and I think most web browsers do the same. This 
avoids an awkward situation where a non-idempotent requests can fail 
because the server has timed out the connection, and it's not safe to 
retry. RFC 2616 section 8.1.4 touches on this.




derek
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Possible configure changes for epoll

2008-06-10 Thread Scott Lamb

Rolf Vandevaart wrote:

Hello:

We embed libevent in the Open MPI project; long ago, we folded 
libevent's configure m4 code into our own configure code.  Over time, we 
tweaked the libevent m4 code for our own purposes as we ran into 
compatibility issues, etc.  We're submitting these changes to you in the 
hopes that they will be useful.  Feel free to use them or disregard them.


We've changed the form of the original m4 so that it's not directly 
[re-]importable to libevent, but perhaps the code can be copied and 
morphed back into your configure.in.  Here's a link to our current 
revision of the libevent-specific m4 in our configure system:


https://svn.open-mpi.org/trac/ompi/browser/trunk/config/ompi_setup_libevent.m4 



Here's a list of the changes that we have made that you might care about 
(there are other changes, too, but I doubt you'll care/want them):


1. Checking for epoll_ctl with AC_CHECK_FUNCS is unfortunately not 
sufficient on some older Linux kernels (e.g., whatever was in Fedora 9) 
because although the function exists and is linkable, it's hardwired to 
return ENOSYS.  So if AC_CHECK_FUNCS with epoll reports that the 
function exists, we also run a short program to ensure that epoll 
actually works.  Doesn't work with cross-compiling, of course.


I suspect what's happening is that the epoll functions exist in libc but 
not the kernel, so the system calls get issued but always fails with 
ENOSYS. glibc and the Linux kernel are versioned independently, so this 
isn't too surprising.


Why do this detection at compile-time rather than run-time? The run-time 
approach seems superior because it does the right thing if run with a 
newer or older kernel than compiled with (which I wouldn't describe as 
cross-compiling per se).


libevent's current run-time ENOSYS support looks okay, in fact. Looks 
like it (incorrectly) returns epoll in event_get_supported_methods(), 
but it will accept an ENOSYS in epoll_create() without complaint and 
move on to the next method. What problem did you encounter?




2. The Sun Studio 12 compilers on Linux currently don't properly support 
the "packed" attribute.  As such, (struct epoll_event) generated by Sun 
Studio 12 on 64 bit architectures will not match the same memory layout 
as in the Linux kernel.  Badness ensues.  In conjunction with #1, our 
test  that checks whether epoll works will also fail if the packed-ness 
of (struct epoll_event) doesn't match between the user application and 
the kernel.  Specifically: the test passes with Sun Studio 12 32-bit 
builds, but fails with Sun Studio 12 64-bit builds (exactly as it should).


We extended the #1 and #2 tests into the syscall test for epoll as well.

--> Including tests #2 and #3 would be most helpful to Sun, because it   
makes libevent compilable by the Sun Studio 12 compilers on Linux.


Yuck. As I'm sure you know, there are many occurrences of packed in 
system headers used by more than just libevent. I'm not the one you'd 
need to convince (I'm not a libevent maintainer), but IMHO, it's not 
feasible to put workarounds in the upstream version of every affected 
package. libevent's relatively easy because it could just not use epoll, 
but other packages would have to do unpleasant things to their structures.


Instead, you (by which I mean Sun, not necessarily you personally) can 
fix your own compiler and, until then, you can (attempt to) maintain 
patches in your distribution to work around its flaws.


4. All versions of OS X kqueue up to and including 10.5.3 are broken 
when used with pty's.  We therefore disable kqueue on OS X because Open 
MPI uses libevent with pty's.  I don't think you want this in the 
general case, but perhaps this a useful datapoint for you.


With libevent trunk, you might be able to use the 
event_get_supported_methods() and event_config_*() support I alluded to 
above and test methods for this bug and exclude them if necessary at 
run-time. Then if run on a hypothetical newer OS X with a fixed kqueue, 
your program would use it without code changes or recompiling.


If using a pty with libevent is common, maybe this test could be put 
into libevent for use via event_config_require_features(cfg, 
EV_FEATURE_PTY). Then all callers could make their own decision without 
having to do the hard work of testing it themselves.




That's it.  Thanks for all your hard work on libevent.

Rolf





Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] bug: handler called again after event_del()

2008-02-11 Thread Scott Lamb

Springande Ulv wrote:
Has anyone else seen this problem on Mac OS X? Otherwise I'll try to 
debug more and come up with more specifics.


Also I also see that libevent seems to enter a while-true loop, grab all 
CPU and freeze during handling of a write|timeout. I have a feeling this 
is related to the spurious kevent notification mentioned above. Has 
anyone seen this as well?___


libevent trunk head works fine for me with kqueue on OS X 10.4. I 
haven't tried libevent 1.4.1-beta or OS X 10.5 yet.


What does test/test.sh say?

Best regards,
Scott
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] evhttp changes for large requests

2008-02-10 Thread Scott Lamb

Scott Lamb wrote:
(4) Detect while streaming that the client connection has been lost, so 
that we know to stop sending chunks. Patch attached to return error code 
in evhttp_send_reply_chunk(). (Wouldn't hurt to add error returns in 
other places, but this is my immediate need.)


Hmm, my patch was still appending to the buffer if the client doesn't 
pay attention; that's probably not ideal either.


(6) Flow control (for the --limit-rate case). I need to keep the 
outgoing connection input buffer, outgoing request input buffer, 
incoming request output buffer, and incoming connection output buffer 
from growing to be ridiculous. I'm considering something like this:


* define read watermarks on requests; it will only read from the 
outgoing connection when the input buffers are below the high (default 
of ~0 to preserve existing behavior). it will only call the chunk 
callback when the input buffers are above the low (default of 0).


* define an option to drain the input buffer after calling the chunk 
callback, defaulting to 1 for existing behavior. I'd want to turn it off 
so I can transfer bytes only if the output buffers are not full.


* define output watermarks as well. If below low watermark (defaulting 
to 0), call a fill function which in my case would also transfer from 
input buffers.


I'm not too attached to this plan. I keep thinking there might be a 
simpler way, but I don't see it.


Hmm, here's a simpler approach (evhttp-flowcontrol.patch). Opinions?

Flow control for evhttp_request

* evhttp_request_set_output_watermarks():
  - call "fill" when "output buffer size <= low watermark" becomes true
  - call "drain" when "output buffer size >= high watermark" becomes true

* evhttp_request_{pause,resume}():
  Pause and resume reading from the socket into the input buffer

My client<->proxy request's fill and drain callbacks resume and pause 
the proxy<->server request, respectively.


I'm wondering if there's any point in input watermarks here or for 
bufferevent either (remove wm_input? there doesn't seem to be an API 
yet). The idea of the downstream thing toggling it seems simpler.


Preliminary version of all patches attached. Still don't have anything 
for (5). These apply in this order:


+ evhttp-64bit-length.patch
+ evhttp-stream-in.patch
+ evhttp-nonchunked-streaming.patch
+ evhttp-detect-failure.patch
> evhttp-flowcontrol.patch

Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>
evhttp: stream incoming responses, even if not chunked

From: Scott Lamb <[EMAIL PROTECTED]>

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---

 libevent/http.c |   19 ++-
 1 files changed, 14 insertions(+), 5 deletions(-)


diff --git a/libevent/http.c b/libevent/http.c
index 500a991..d4d0ce6 100644
--- a/libevent/http.c
+++ b/libevent/http.c
@@ -730,11 +730,6 @@ evhttp_handle_chunked_read(struct evhttp_request *req, 
struct evbuffer *buf)
EVBUFFER_DATA(buf), req->ntoread);
evbuffer_drain(buf, req->ntoread);
req->ntoread = -1;
-   if (req->chunk_cb != NULL) {
-   (*req->chunk_cb)(req, req->cb_arg);
-   evbuffer_drain(req->input_buffer,
-   EVBUFFER_LENGTH(req->input_buffer));
-   }
}
 
return (0);
@@ -768,7 +763,21 @@ evhttp_read_body(struct evhttp_connection *evcon, struct 
evhttp_request *req)
req->ntoread = 0;
evhttp_connection_done(evcon);
return;
+   } else if (req->chunk_cb != NULL) {
+   /*
+* The condition above is simply for efficiency; we do the
+* move at the end if we aren't streaming.
+*/
+   req->ntoread -= EVBUFFER_LENGTH(buf);
+   evbuffer_add_buffer(req->input_buffer, buf);
}
+
+   if (EVBUFFER_LENGTH(req->input_buffer) > 0 && req->chunk_cb != NULL) {
+   (*req->chunk_cb)(req, req->cb_arg);
+   evbuffer_drain(req->input_buffer,
+   EVBUFFER_LENGTH(req->input_buffer));
+   }
+
    /* Read more! */
event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
EVHTTP_BASE_SET(evcon, &evcon->ev);
evhttp: use a 64-bit Content-Length: counter even on 32-bit platforms

From: Scott Lamb <[EMAIL PROTECTED]>

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---

 libevent/evhttp.h |2 +-
 libevent/http.c   |4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)


diff --git a/libevent/evhttp.h b/libevent/evhttp.h
index 20a33b9..a47a2f0 100644
--- a/libevent/evhttp.h
+++ b/libevent/evhttp.h
@@ -204,7 +204,7 @@ struct {
char *response_code_line;   /* Rea

Re: [Libevent-users] evhttp changes for large requests

2008-02-10 Thread Scott Lamb

Scott Lamb wrote:
(1) Use a 64-bit counter for tracking the Content-Length:. Patch 
attached. (Somehow this patch isn't working, though? curl complains that 
it's stopping at 2^31-1 bytes. I may debug later.)


Ahh. My tired eyes missed the most important assignment. Working patch 
attached.
evhttp: use a 64-bit Content-Length: counter even on 32-bit platforms

From: Scott Lamb <[EMAIL PROTECTED]>

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---

 libevent/evhttp.h |2 +-
 libevent/http.c   |2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libevent/evhttp.h b/libevent/evhttp.h
index 20a33b9..a47a2f0 100644
--- a/libevent/evhttp.h
+++ b/libevent/evhttp.h
@@ -204,7 +204,7 @@ struct {
char *response_code_line;   /* Readable response */
 
struct evbuffer *input_buffer;  /* read data */
-   int ntoread;
+   int64_t ntoread;
int chunked;
 
struct evbuffer *output_buffer; /* outgoing post or data */
diff --git a/libevent/http.c b/libevent/http.c
index 712a899..07d1567 100644
--- a/libevent/http.c
+++ b/libevent/http.c
@@ -707,7 +707,7 @@ evhttp_handle_chunked_read(struct evhttp_request *req, 
struct evbuffer *buf)
event_free(p);
continue;
}
-   req->ntoread = strtol(p, &endp, 16);
+   req->ntoread = strtoll(p, &endp, 16);
error = *p == '\0' || (*endp != '\0' && *endp != ' ');
event_free(p);
if (error) {
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


[Libevent-users] evhttp changes for large requests

2008-02-10 Thread Scott Lamb
I've written a simple libevent-based HTTP proxy, and now I'd like it to 
work with large requests:


$ curl --proxy localhost:8080 \
   http://localhost/hugefile

$ curl --proxy localhost:8080 --max-time 1 \
   http://localhost/hugefile

$ curl --proxy localhost:8080 --limit-rate 1k \
   http://localhost/hugefile

To do that I need some changes. I have some preliminary patches (no 
tests yet).



(1) Use a 64-bit counter for tracking the Content-Length:. Patch 
attached. (Somehow this patch isn't working, though? curl complains that 
it's stopping at 2^31-1 bytes. I may debug later.)



(2) Stream incoming responses. Always call a non-NULL chunk_cb when we 
get more data, not just when using chunked encoding. Patch attached.



(3) Stream large responses (to avoid huge memory use and high latency) 
with "Content-Length:" rather than "Transfer-Encoding: chunked" when 
possible so that client-side progress indicators work properly. Patch 
attached.



(4) Detect while streaming that the client connection has been lost, so 
that we know to stop sending chunks. Patch attached to return error code 
in evhttp_send_reply_chunk(). (Wouldn't hurt to add error returns in 
other places, but this is my immediate need.)



(5) Abort an outgoing request. Maybe evhttp_request_free() should do 
this if the request is active? or add an explicit evhttp_request_abort()?



(6) Flow control (for the --limit-rate case). I need to keep the 
outgoing connection input buffer, outgoing request input buffer, 
incoming request output buffer, and incoming connection output buffer 
from growing to be ridiculous. I'm considering something like this:


* define read watermarks on requests; it will only read from the 
outgoing connection when the input buffers are below the high (default 
of ~0 to preserve existing behavior). it will only call the chunk 
callback when the input buffers are above the low (default of 0).


* define an option to drain the input buffer after calling the chunk 
callback, defaulting to 1 for existing behavior. I'd want to turn it off 
so I can transfer bytes only if the output buffers are not full.


* define output watermarks as well. If below low watermark (defaulting 
to 0), call a fill function which in my case would also transfer from 
input buffers.


I'm not too attached to this plan. I keep thinking there might be a 
simpler way, but I don't see it.



Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>
evhttp: stream incoming responses, even if not chunked

From: Scott Lamb <[EMAIL PROTECTED]>

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---

 libevent/http.c |   19 ++-
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/libevent/http.c b/libevent/http.c
index 07d1567..94c3a0f 100644
--- a/libevent/http.c
+++ b/libevent/http.c
@@ -730,11 +730,6 @@ evhttp_handle_chunked_read(struct evhttp_request *req, 
struct evbuffer *buf)
EVBUFFER_DATA(buf), req->ntoread);
evbuffer_drain(buf, req->ntoread);
req->ntoread = -1;
-   if (req->chunk_cb != NULL) {
-   (*req->chunk_cb)(req, req->cb_arg);
-   evbuffer_drain(req->input_buffer,
-   EVBUFFER_LENGTH(req->input_buffer));
-   }
}
 
return (0);
@@ -768,7 +763,21 @@ evhttp_read_body(struct evhttp_connection *evcon, struct 
evhttp_request *req)
req->ntoread = 0;
evhttp_connection_done(evcon);
return;
+   } else if (req->chunk_cb != NULL) {
+   /*
+* The condition above is simply for efficiency; we do the
+* move at the end if we aren't streaming.
+*/
+   req->ntoread -= EVBUFFER_LENGTH(buf);
+   evbuffer_add_buffer(req->input_buffer, buf);
}
+
+   if (EVBUFFER_LENGTH(req->input_buffer) > 0 && req->chunk_cb != NULL) {
+   (*req->chunk_cb)(req, req->cb_arg);
+   evbuffer_drain(req->input_buffer,
+   EVBUFFER_LENGTH(req->input_buffer));
+   }
+
/* Read more! */
event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
    EVHTTP_BASE_SET(evcon, &evcon->ev);
evhttp: stream large responses without requiring chunking

From: Scott Lamb <[EMAIL PROTECTED]>

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---

 libevent/http.c |9 +++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/libevent/http.c b/libevent/http.c
index 94c3a0f..9d9ddea 100644
--- a/libevent/http.c
+++ b/libevent/http.c
@@ -1719,8 +1719,13 @@ evhttp_send_reply_start(struct evhttp_request *req, int 
code,
/* set up to watch for client close */
evhtt

[Libevent-users] [PATCH] benchmark chart generator

2007-12-29 Thread Scott Lamb
I was frustrated with the gap between bench.c and decent charts, so I 
made the attached patch. It adds a simple Python program to generate 
these with gnuplot. I've also attached sample output (one-active.png).


Best regards,
Scott


--
Scott Lamb <http://www.slamb.org/>
<>Add a chart generator.

Also clean up what appears to be a totally extraneous error output from
bench.c.

Index: test/chartbench.py
===
--- test/chartbench.py  (revision 0)
+++ test/chartbench.py  (revision 0)
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+"""
+%prog [options]
+
+Creates libevent benchmark charts.
+
+Requirements:
+* Python >= 2.4 for the subprocess module
+* test-init and bench in current directory
+* gnuplot with png output format (and optionally freetype support)
+"""
+
+from __future__ import division
+
+import optparse
+import os
+import subprocess
+import sys
+import traceback
+
+ALL_METHODS = 'kqueue devpoll poll select epoll evport'.split(' ')
+
+STYLE_MAP = {
+'candlesticks': 'using 1:3:2:6:5 with candlesticks linewidth 2',
+'lines': 'using 1:4 with lines linewidth 2 smooth csplines',
+}
+
+def get_environment(method):
+"""Returns an environment that makes libevent use the specified method."""
+env = {}
+for i in ALL_METHODS:
+if i != method:
+env['EVENT_NO%s' % i.upper()] = 'yes'
+return env
+
+def median(data):
+"""Returns the median of a sorted list of numbers."""
+n = len(data)
+if n % 2 == 0:
+return (data[n//2] + data[n//2+1]) / 2
+else:
+return data[n//2]
+
+def run_bench(method, pipes, active, writes):
+"""Gets candestick bounds for a given test.
+
+Returns (minimum, first quartile, median, third quartile, maximum).
+"""
+print 'run_bench(%r, %d, %d, %d)' % (method, pipes, active, writes)
+
+# Get the data.
+bench = subprocess.Popen(('./bench -n %d -a %d -w %d'
+  % (pipes, active, writes)).split(' '),
+ bufsize=1, stdout=subprocess.PIPE,
+ env=get_environment(method))
+data = [float(line) for line in bench.stdout]
+retval = bench.wait()
+if retval != 0:
+raise Exception('bench returned %d' % retval)
+if not data:
+raise Exception('bench returned insufficient data')
+
+# Now get our statistics.
+data.sort()
+return (data[0],
+median(data[0:len(data)//2]),
+median(data),
+median(data[len(data)//2:]),
+data[-1])
+
+def escape(literal):
+"""Escapes the given literal for use in gnuplot control channel.
+
+See gnuplot's "help syntax" for details."""
+return ('"%s"' % literal.replace('\\', '')
+.replace('"', '\\"')
+.replace('\n', '\\n'))
+
+def plot(filename, title, options, methods, active, writes):
+"""Creates the plot described by the arguments."""
+
+# Launch gnuplot. It wants to poke around at my environment, so I won't
+# give it one. (At least if it gets an unusable $DISPLAY, it's unhappy.)
+if options.store_commands:
+gnuplot_out = open('%s.plot' % filename, 'w')
+else:
+gnuplot = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE,
+   env={'PATH': os.environ['PATH']})
+gnuplot_out = gnuplot.stdin
+
+if options.font is None:
+gnuplot_out.write('set terminal png\n')
+else:
+gnuplot_out.write('set terminal png font %s %d\n'
+  % (escape(options.font), options.fontsize))
+gnuplot_out.write("""
+set output %(filename)s
+set title %(title)s
+set xlabel "Inactive file descriptors"
+set ylabel "Time (\xC2\xB5s)"
+set palette color
+set style fill solid
+set key top left
+set logscale y 10
+set style line 1 lc rgb "#88"
+set border 3 linestyle 1
+set xtics out nomirror textcolor rgb "#00"
+set ytics out nomirror textcolor rgb "#00"
+set grid
+""" % {
+'title': escape(title),
+'filename': escape(filename),
+})
+gnuplot_out.write('plot [0:] [] ' +
+', '.join(['"-&qu

Re: [Libevent-users] SO_LINGER option for sockets created by evhttp

2007-12-14 Thread Scott Lamb

Marc Lehmann wrote:

On Fri, Dec 14, 2007 at 12:56:00PM -0800, Scott Lamb <[EMAIL PROTECTED]> wrote:

Tests and results here:

http://www.slamb.org/svn/repos/trunk/projects/socket_tests/index.html


"The UNIX socket API has been standardized for a decade. But the standards
are vague on a lot of critical behavior."

In defendence of the standards (in this case the single unix spec.),
the blocking behaviour is _mandated_ by the SUS, and not following this
behaviour is a bug if the platform claims to follow unix behaviour. Of
course, OS X is quite far from any unix behaviour, so the portability
problem remains.

The problems are, however, far fewer in number if one only tests unix
platforms, which also have problematic behaviours but overall perform much
better than the unix emulation in os x.


I'm not going to get into stupid hairsplitting about what "unix 
emulation" vs "unix platforms" means, but OS X's networking code was 
largely inherited from FreeBSD. I would expect older FreeBSD systems to 
have the same behavior.



However, that page has a lot of problems, for example it requires
non-standard behaviour and declares standard behaviour as "failure", an
example would be:

   read(0) while connecting

   EWOULDBLOCK failure (linux)
   0   failure (os x)

EWOULDBLOCK is not a standard error code, the standard only documents EAGAIN
(which is what linux actually returns). The test expects EINPROGRESS, but
that is not allowed by the unix standard, so a platform actually getting a
green status there would be _broken_.


EWOULDBLOCK is how the Python library reported the error. On Linux, 
EWOULDBLOCK and EAGAIN are synonymous.




Also, returning 0 is also allowed in this case, so the os x test is also
errornously marked as failing, when, in fact, it is fully standards
compliant.

So while the raw results of that page are very interesting, it would be
more useful if the interpretation as failure or not would not _require_
behaviour that is wrong by de-facto and actual standards.



I chose "failure" vs. "success" criteria rather arbitrarily - especially 
in the cases where I couldn't find a clear answer in the standard, they 
 were basically just "was it the same as the first platform I tried 
that test on". I should probably remove the color coding.


If you take a more thorough look at the page, you'll see a note to that 
effect.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] SO_LINGER option for sockets created by evhttp

2007-12-14 Thread Scott Lamb

Ilya Martynov wrote:

Hi,

I wonder if anybody could elaborate what is the reason for setting
SO_LINGER option for sockets created by evhttp. I mean this part of code
inside of http.c:

static int
bind_socket_ai(struct addrinfo *ai)
{
...
linger.l_onoff = 1;
linger.l_linger = 5;
setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&linger,
sizeof(linger));
...
}

If I'm reading the documentation correctly at least for Linux this
makes close() on the socket to block what probably not a very good thing
in programs based on libevent. From
http://linux.about.com/od/commands/l/blcmdl7_socket.htm:

SO_LINGER
Sets or gets the SO_LINGER option. ... When enabled, a close(2) or
shutdown(2) will not return until all queued messages for the socket
have been successfully sent or the linger timeout has been reached.
Otherwise, the call returns immediately and the closing is done in the
background.



I ran a bunch of tests on linger a while ago (by creating a socket pair 
and programmatically manipulating firewall rules to simulate packet 
loss). My results agree with your conclusion - this can cause the 
process to block for l_linger seconds on Linux. On OS X, this does *not* 
block if the socket is non-blocking - the behavior is not consistent 
between platforms.


My conclusions were basically that the only use of SO_LINGER is to force 
an RST by passing {1, 0}. The default is {0, 0}.


Tests and results here:

http://www.slamb.org/svn/repos/trunk/projects/socket_tests/index.html

I didn't test if linger options are inherited from the listen socket to 
accepted sockets, which this code seems to be assuming.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


[Libevent-users] RFC - evdns client API

2007-11-10 Thread Scott Lamb
I'm trying to use the evdns client API for the first time (in tinc-1.1),
and I've noticed a few things:

1. There's no threadsafe API (see ticket 1827379). This is not necessary
for tinc but is good to have in general.

2. There's no way to cancel an outstanding resolve. (see ticket 1827307)
this is important for tinc, which can stop a connection attempt for
reasons of its own. I either need this or to allocate/track a resolver
structure on my own so the callback doesn't crash the program.

3. There's a resolve function for each address family, so callers have
to explicitly support IPv6 with extra code. This would not be necessary
if libevent were to provide a getaddrinfo()-style interface.

I propose a new API to address all of these points in a unified way. I
have a starting point below. I only put in a "cooked" interface because
that's what I would like for my current program, but I would not object
to a "raw" interface that shares the same "struct evdns_client" and
"evdns_client_op". (In fact, one would be necessary internally to
implement this side-by-side with the existing API.)

My primary question to reviewers here is source vs. binary compatibility
of future versions. I'm tempted to shoot for binary compatibility, but
I'm not sure if it's worth it given that other libevent APIs ("struct
event", "struct bufferevent") have chosen the other route. ("struct
evhttp_request" seems to be on the fence - the structure is in the
public header, but the comments suggest you should use accessors instead.)

Here are the event_dns.h additions:

/**
 * Create a new DNS resolver client.
 * @param base Operate with the given event_base
 * @param attrs Use the specified initialization attributes.
 *  NULL is currently the only acceptable value.
 *  (To reviewers: this is for future expansion; it
 *  could hold evdns_resolv_conf_parse arguments,
 *  among other things.)
 */
struct evdns_client *evdns_client_new(struct event_base *base,
  struct event_resolver_attr
  *attrs);

/**
 * Free the DNS resolver client.
 * All outstanding operations will be canceled.
 */
void evdns_client_free(struct evdns_client *);

/**
 * A cancelable DNS client operation.
 * As with "struct event", the caller must keep this structure
 * in-place from evdns_resolve_*() to callback or
 * evdns_request_cancel().
 *
 * (To reviewers: the definition should be fairly immutable for
 * binary compatibility; maybe just a pointer to the
 * "struct request".)
 */
struct evdns_client_op;

/** Cancels a pending DNS resolution. */
int evdns_client_op_cancel(struct evdns_client *,
   struct evdns_client_op *);

/**
 * Results from evdns's "cooked" client resolver.
 *
 * (To reviewers: this is a structure rather than direct args
 * to allow future expansion without breaking source compatibility.
 * Because the caller never does the allocation, we could even
 * maintain binary compatibility by making this an opaque structure
 * with accessor functions.)
 */
struct evdns_cooked_results {
/**
 * Time (in seconds) until cache expiry.
 *
 * (To reviewers: I'm considering the expiry directly available
 * as "expiry" and exposing gettime() as event_gettime() for
 * comparison. It seems most callers wanting to use the TTL
 * will have to do this translation in the callback, and
 * perhaps reimplement gettime() for a stable clock.)
 */
int ttl;

/**
 * Individual results, which must be freed with
struct evdns_cooked_result *results;
};

/**
 * A single cooked result.
 *
 * (To reviewers: could also be opaqued for binary compatibility
 * with member accessors or even
 * evdns_cooked_result_{socket,connect,bind,str}().)
 */
struct evdns_cooked_result {
struct evdns_cooked_result *next;

/**
 * Socket family (for first argument of socket()).
 * (To reviewers: sa.sa_family may do instead? I'm not sure
 * why getaddrinfo() has a member like this.)
 */
int sock_family;

/** Socket type (for second argument of socket()). */
int sock_type; /**< for socket() */

/** Socket protocol (for third argument of socket()). */
int sock_protocol;

/**
 * Socket length (for third argument of connect() and bind()).
 * Note sa.sa_len is not portable.
 */
socklen_t salen;

struct sockaddr sa; /* MUST BE LAST - HIDDEN EXTRA SPACE HERE */
};

/**
 * Free cooked results.
 * @param res As with free() itself, may be NULL.
 */
void evdns_cooked_results_free(struct evdns_cooked_results *res);

/**
 * Cooked results callback.
 * @param err Can be used with evdns_err_to_string
 * @param res If non-null, results. Must be freed with
 *evdns_cooked_results_free().
 */
void (*evdns_cooked_resolve_cb_t)(int err,
  struct evdns_cooked_results *res,
  void *cbarg

Re: [Libevent-users] [PATCH] signal.c, evsignal.h: properly save/restore previous signal handlers and fix memory stomp

2007-11-09 Thread Scott Lamb

Christopher Layne wrote:

-   if (!base->sig.ev_signal_added) {
-   base->sig.ev_signal_added = 1;
-   event_add(&base->sig.ev_signal, NULL);
+   if (!sig->ev_signal_added) {
+   sig->ev_signal_added = 1;
+   event_add(&sig->ev_signal, NULL);
}
There's a bug here (that predates your change): this code should handle 
event_add() failure. (E.g., epoll_ctl() returning ENOMEM.)


Fix in same, or sweep up in a later patch? How many other places are
there where we're not currently checking the return value of
event_add()? If there are more than this, we might as well just do it
separately.

-cl


Looks like there are a number of others:

* evsignal_cb <- evsignal_add() should probably be using EV_PERSIST so 
this call is unnecessary


* bufferevent_read_cb
* bufferevent_read_pressure_cb
* bufferevent_write_cb
* bufferevent_write
* evdns_add_server_port
* evdns_server_request_respond
* evhttp_add_event
* evhttp_connection_start_detectclose
* evhttp_bind_socket

Most look straightforward to fix, but I'm not sure how the callbacks 
should indicate error.


There are also several unchecked event_del() calls, but I think it's 
safe to assume those will fail only on logic error.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] signal.c, evsignal.h: properly save/restore previous signal handlers and fix memory stomp

2007-11-09 Thread Scott Lamb

Christopher Layne wrote:

+   /* save previous handler setup */
+   if (sigaction(evsignal, NULL, sig->sa_old[evsignal]) == -1
+   || sigaction(evsignal, &sa, NULL) == -1)


Not worth changing unless you're redoing the patch anyway, but is there 
some reason you aren't doing this in a single call? I.e.,


if (sigaction(evsignal, &sa, sig->sa_old[evsignal]) == -1) {

...


-   if (!base->sig.ev_signal_added) {
-   base->sig.ev_signal_added = 1;
-   event_add(&base->sig.ev_signal, NULL);
+   if (!sig->ev_signal_added) {
+   sig->ev_signal_added = 1;
+   event_add(&sig->ev_signal, NULL);
}


There's a bug here (that predates your change): this code should handle 
event_add() failure. (E.g., epoll_ctl() returning ENOMEM.)

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-05 Thread Scott Lamb

Marc Lehmann wrote:

On Sun, Nov 04, 2007 at 09:37:52PM -0800, Scott Lamb <[EMAIL PROTECTED]> wrote:

There is actually a lot of code that relies on this just working, and the
only other event loop I know that has a problem with this is Tk.

Ugh, I'd argue that idiom is broken. But if the support's free, I guess
it doesn't matter.


Well, the idiom is how it works in most languages nowadays, so wether broken
or not its important to support.

The main problem is that with the current libevent implementation, failures
are completely silent.


I've used garbage-collected languages without this problem. It's not the 
language; it's the idiom.



This is true, but its an optional feature you don't have to use.  In case
you wonder, EV, the perl interface to libev, uses this feature.

It makes most sense when embedding, of course (not all the world is an .so
:).

Hmm, in your Perl example, I wouldn't rule out you wanting to share the
event loop with some C-based library and being unable to do so.


If you want to share it, you of course cannot do that unless that c-based
library uses the same version of the code.

But this is in no way difefrent to libevent: if one program links it
statically and other shared, or if one program uses 1.3d and another 1.3e
(different sonames), then you can't share it either.


The former is of course the fault of the linking program. The latter is
fixed (recently); libevent is now versioning properly.


There's definitely nothing you can't do with a void*, so this is all a
question of efficiency.


Its also a question of coding overhead, which is probably more important than
efficiency in this case.

Especially as efficieny is a red herring. in the libev proposed api,
callbacks get the watcher object passed, which

a) is often what you want anyways
b) is allocated by user code, so you cna just make the struct larger
   by appending your data.

this solves the efficiency issue and also makes for a simpler API.

In fact, I pondered long on wether I even add a void *arg to each event
watcher, but I thought the overhead of havign to "subclass" is large in the
common case where a single pointer indeed is enough.

In any case, let me repeat that this is an optional feature, not a
limitation, in the API.


It is an invitation for abuse (losing compatibility).


I assert that the cost of a sizeof(void*) to
point to the relevant part of your structure (which can be
nearby...still reasonable cache locality) is not too high.


Its higher than necessary, and more complex than neccessary.


Higher than necessary? I don't care; it's worth it.

More complex than necessary? Not really.


All callbacks will be called with EV_ERROR when an error occurs. And yes,
if you don't do error handlign and endlessly retry the same operation in a
loop, you run into problems.

But as that is an obvious programming bug, I don't see any problem here.

Hmm. Let me introduce a use case: an event-driven program which must not
fail. init or similar.

I worked on such a program recently. If it were unreliable, you would
have to send the system back to the factory for repair (i.e., flashing
new software). On ENOMEM, it would basically sleep and retry. This was
quite successful (memory could be temporarily consumed by network
buffers, etc, which cleared itself up after a while).


This could be solved easier with having a generic callback thats called in
such special conditions.

The alternative to have every event_add etc. call surrounded by checking
code is not realistic, especially if some of the code is not easily
changable (such as the libevent code itself which doesn't check for such
errors!).


For this program, it's important to know more than that an error has
occurred. EV_ERROR is totally inadequate.


You already know more: you know which watcher caused it, or which watcher is
responsible.


Erm, no. In the ENOMEM case, I know which fd you decided to kill, though
not actually that you've killed it. ENOMEM is not a per-file descriptor
problem.


What is my program supposed to do? It can't distinguish them, and the
correct behavior in each of these conditions is totally different. Also,
in the program I'm thinking of, "libev chose to kill this file
descriptor" probably means a network link just went down. Ergh.


killing the file descriptor might indeed be harsh. all that libev does now is
stop the event watcher and signal an error.


That's better...in the sense that "we've stopped murdering people; now
we only beat them severely" is better.


Besides, if you cannot malloc the few bytes ev_once requires you need a
*lot* of good error handlign code to continue sensibly.

Yes, as I've mentioned above, there are programs for which this level of
error handling is necessary.


I agree, but libevent already doesn't provide this, so its moot to compare
th

Re: Heap-based timer implementation (was Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent)

2007-11-05 Thread Scott Lamb

Nick Mathewson wrote:

In case anybody here isn't watching the commits list [1], Niels
applied a patch from Maxim Yegorushkin to make the timeout
implementation based on a heap, rather than a RB-tree.  Thanks, Maxim!

This will probably need some testing; if anybody wants to play around
with it, just check out the SVN trunk [2] and send in any bugs you run
into, or any improvements that we should make.


Very nice. I hope to see any other internal improvements from libev make 
it into the libevent codebase one at a time in patch form.


And then, perhaps, API changes considered? I have to admit, I have a few 
complaints with the libevent API myself. Maybe all API changes should be 
discussed and you/Niels can determine if it's worth finding a way to 
make a (hopefully backwards compatible) transition?


Best regards,
Scott
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-05 Thread Scott Lamb

Marc Lehmann wrote:

On Sun, Nov 04, 2007 at 09:56:44PM -0800, Scott Lamb <[EMAIL PROTECTED]> wrote:

returning from event_loop, leaving the app unclear on what has happened
and what to do.

In any case, you can get the same behaviour as libevent by calling unloop
in case of an error, so the interface is strictly more powerful.

Another reason this is undesirable: to get the libevent behavior, I'd
have to have this logic in *every callback* to get the same behavior.


Hmm, one could actually roll this into the libevent compatibility
layer. I'll think about this (didn't occur to me before).

Note, however, that I think the libevent interface is undesirable, as it
leaves me unclear on what happened and no reasonable way to recover (e.g.
in the case of EBADF in select).


No, as I said before, libevent retains errno. I've attached a 
demonstration program. If it doesn't return 0 when run against your 
libevent emulation layer, your code is broken.



Also, with libevent, you would need similar logic around each call to
event_add/del and so on, because those can all fail in libevent, so its just
a different place, really.


It's not just a different place - it's where the failure happened.



(And I do think I will provide an oom-error handler for this specific
case, as it is about the only generic error that isn't specific to some
watcher).

Thanks for these ideas,



#include 
#include 
#include 
#include 
#include 
#include 

const int BADFD = 64;

static void
cb(int fd, short events, void *cbarg)
{
}

int
main(int argc, char **argv)
{
struct event ev;
int sts;
const char *method;

/* Initialize, hopefully with select method */
putenv("EVENT_NOKQUEUE=yes");
putenv("EVENT_NODEVPOLL=yes");
putenv("EVENT_NOPOLL=yes");
putenv("EVENT_NOEPOLL=yes");
putenv("EVENT_NORTSIG=yes");
putenv("EVENT_NODEVPORT=yes");
event_init();
method = event_get_method();
if (strcmp(method, "select") != 0)
return EXIT_FAILURE;

/* add a bad descriptor */
close(BADFD); /* just to be sure */
event_set(&ev, BADFD, EV_READ|EV_PERSIST, cb, NULL);
sts = event_add(&ev, NULL);
if (sts != 0)
return EXIT_FAILURE;

/* try dispatching */
sts = event_dispatch();
if (sts != 0) {
perror("event_dispatch");
return (errno == EBADF) ? EXIT_SUCCESS : EXIT_FAILURE;
}

return EXIT_FAILURE;
}
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] sensible thread-safe signal handling proposal

2007-11-04 Thread Scott Lamb
Christopher Layne wrote:
> On Sun, Nov 04, 2007 at 04:23:01PM -0800, Scott Lamb wrote:
>>> It wasn't what I expected; I was fully confident at first that the
>>> thread-pool, work-queue model would be the way to go, since it's one
>>> I've implemented in many applications in the past. But the numbers said
>>> otherwise.
>> Thanks for the case study. To rephrase (hopefully correctly), you tried
>> these two models:
>>
>> 1) one thread polls and puts events on a queue; a bunch of other threads
>> pull from the queue. (resulted in high latency, and I'm not too
>> surprised...an extra context switch before handling any events.)
> 
> So back to this..
> 
>> 2) a bunch of threads read and handle events independently. (your
>> current model.)
> 
> BTW: How does this model somehow exempt itself from said context switching
> issue of the former?

Hmm, William Ahern says that at least on Linux, they only wake one
thread per event. That would explain it.

>> Did you also tried the so-called "leader/follower" model, in which the
>> thread which does the polling handles the first event and puts the rest
>> on a queue; another thread takes over polling if otherwise idle while
>> the first thread is still working. My impression this was a widely
>> favored model, though I don't know the details of where each performs best.
> 
> Something about this just seems like smoke and mirrors to me. At the end of
> the day we still only have a finite amount of CPU cores available to us and
> any amount of playing with the order of things is not going to extract any
> magical *more* throughput out of a given box. Yes, some of these methods
> influence recv/send buffers and have a cascading effect on overall throughput,
> but efficient code and algorithms are going to make the real difference - not
> goofy thread games.
> 
> (and this is coming from someone who *likes* comp.programming.threads)

Oh, I don't know, there is something to be said for not making a handoff
between threads if you can avoid it. You're not going to get more
throughput than n_cores times what you got with one processor, but I'd
expect avoiding context switches and cache bouncing to help you get
closer to that.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Scott Lamb wrote:
>>> * What's your use case for ev_loop_new() and ev_loop_default()'s bitmask
>>> of allowed implementations?
>> libevents unconditional use of getenv raised concerns with me and
>> apperently some users on this list, too, so this is one way to disable
>> this (EVMETHOD_ANY instead of EVMETHOD_ALL). Also, I am sure some apps
>> want control over the allowed event loops, e.g. to rule out select becasue
>> it is known to be not wrokign for them.
> 
> Ahh, I'd have to agree that getenv() seems sketchy. But with the
> interface you've supplied, you can't simply blacklist select() without

Hmm. I was going to check this out more and forgot before sending the email.

Realistically, I think unit tests and bug reports/workarounds are about
the only reason to blacklist specific event dispatchers. select() sucks,
but well, that's why it's at the bottom of the list, right?

If you are really concerned about syscall overhead (you mentioned it in
another context, though I don't think it should be a major concern), you
might want to prefer poll() to epoll() or kqueue() if you're going to
use a loop a couple times on a small number of fds then throw it away.
But that's a situation where you'd want a little more coarseness: low
startup overhead methods vs. low per-socket overhead ones. Resorting to
naming specific event mechanisms seems undesirable in terms of older
programs taking advantage of newer event facilities.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Marc Lehmann wrote:
>> That seems rather undesirable for many applications.
> 
> Well, its arguably better than libevents behaviour, which is simply
> returning from event_loop, leaving the app unclear on what has happened
> and what to do.
> 
> In any case, you can get the same behaviour as libevent by calling unloop
> in case of an error, so the interface is strictly more powerful.

Another reason this is undesirable: to get the libevent behavior, I'd
have to have this logic in *every callback* to get the same behavior.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Marc Lehmann wrote:
> On Sun, Nov 04, 2007 at 04:09:08PM -0800, Scott Lamb <[EMAIL PROTECTED]> 
> wrote:
>> Have you seen the new Linux timerfd API? Where available, you can wait
>> for CLOCK_MONOTONIC and CLOCK_REALTIME events independently. Beats
>> heuristics,
>
> How? I still need to detect time jumps. If my ev_periodic is to be scheduled
> every minute, on the minute, and somebody resets the time the timer needs to
> be rescheduled. With timerfd I would need to detetc that and remove/insert
> the timer again.

My impression was you could create such a timer like this:

struct itimerspec it = {
.it_value= { .tv_sec = 0,  .tv_nsec = 0 },
.it_interval = { .tv_sec = 60, .tv_nsec = 0 },
};

sts = timerfd(my_timerfd, CLOCK_REALTIME, TFD_TIMER_ABSTIME, &it);

and any adjustments are the kernel's responsibility. It is aware of the
adjtime() calls and such as they happen.

I have not tested this myself.

> (You might have no use for periodics for timeouts, but they are designed
> to solve this very problem :)
> 
> Besides, having a syscall per timer (or even timer change) would be an
> enourmous overhead for many workloads.

Really? Syscalls aren't really *that* expensive in and of themselves,
and it'd be a rare application that makes an order of magnitude more
timerfd() calls than read()/write() calls.

> 
>> and detecting time jumps sound like introducing a lot of extra
>> timeouts.
> 
> I don't quite see how that would happen with either timer event currently in
> libev, unless the user code forces it.
> 
>> I'd hate to see libev(ent)? show up on PowerTOP after just getting rid
>> of the 5-second timeout.
> 
> Now idea what powertop is, but sporiadic servers might use a lot of cpu
> without the kernel ever realising it :)

PowerTOP is a Linux tool for seeing the top causes of timeouts. Recently
people are trying to make better use of processor idle states, so it's
important to not fire timeouts unnecessarily.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Marc Lehmann wrote:
> On Sun, Nov 04, 2007 at 05:04:25PM -0800, Scott Lamb <[EMAIL PROTECTED]> 
> wrote:
>>> * multiple watchers can wait for the same event, there is no limitation
>>>   to one or two watchers for signals and io.
>> Could you give me an example of where that is important?
> 
> Mostly in environments using some form garbage collection. For example,
> this idiom is common in Perl:
> 
>$event = EV::io $fd, ...
> 
> If $event happens to contain an old watcher and $fd happens to refer to
> the same fd as that old watcher, this will lead into probelms as the
> watchers are both alive for a short time.
> 
> There is actually a lot of code that relies on this just working, and the
> only other event loop I know that has a problem with this is Tk.

Ugh, I'd argue that idiom is broken. But if the support's free, I guess
it doesn't matter.

>>> * there are two types of timers, based on real time differences and wall
>>>   clock time (cron-like). timers can also be repeating and be reset at
>>>   almost no cost (for idle timeouts used by many network servers). time 
>>> jumps
>>>   get detected reliably in both directions with or without a monotonic 
>>> clock.
>> (See my other mail about Linux's new timerfd facility.)
> 
> (timerfd unfortunately makes little sense for this, as it adds overhead
> but I can't see the compelling advantage, as one will still run into the
> same time jump problems with periodic timers).
> 
>> Nice; repeating and absolute timers have come up several times before, too.
> 
> This was something I always missed in event loops. That is, some event
> loops have one timer type, some the other, but never both.
> 
>>> * timers are managed by a priority queue (O(1) for important operations
>>>   as opposed to O(log n) in libevent, also resulting in much simpler code).
>> In terms of concrete data types, you appear to have used a binary heap?
>> So by "important operations" you mean removal, correct?
> 
> removal: O(log n)
> insertion: O(log n)
> find next: O(1)
> 
>> still O(log n)? The asymptotic behavior is no different, then, as
>> insertion happens at least as often as removal.
> 
> Yes, but:
> 
> a) finding the next timwer is a constant time issue
> b) a red-black tree is more than three times as slow
> 
> (see the updated benchmark at http://libev.schmorp.de/bench.html,
> especially the difference between the first (no timers) and the second
> examples (timers in use))

Ahh, very nice benchmarks.

> 
>>> * I added idle watchers, pid watchers and hook watchers into the event loop,
>>>   as is required for integration of other event-based libraries, without
>>>   having to force the use of some construct around event_loop.
>> Pardon my ignorance, but what are hook watchers?
> 
> if you want to plug-in other event-based libraries into the event loop you
> need to get to be able to hook into the event loop. this is what those
> watcher types provide.
> 
> the alternative would be to write your own event_loop with EV_NONBLOCK, but
> that isn't modular, that is, if you have two difefernt sofwtare modules
> having their own event_loop you *must* use, you lose. prepare/check watchers
> use this problem nicely.
> 
> A number of event loops have them, and they are useful for other things,
> such as transpoarently integrating coroutine packages etc.
> 
> Its not a killer feature, just very very useful in some cases.
> 
>> pid watchers I assume to be a fancy SIGCHLD handler?
> 
> Yes.
> 
>> That's a potentially useful feature, but why would it require a
>> construct around event_loop?
> 
> I don't udnerstand that, there is no construct around event_loop, its handled
> completely seperately.

My question was in response to your "I added idle watchers, pid watchers
and hook watchers into the event loop, as is required for integration of
other event-based libraries, without having to force the use of some
construct around event_loop."

> The reason is exists is allowing to share this potentially unsharable
> resource. For example, poll and select let you do "everything" (with fds),
> but you can of course only have one component per (single-thread) process
> using them, as they are blocking.
> 
> The same thing is true for signals: you can't share them with sigaction, as
> sigaction only allows one user.
> 
> And the same thing is true for sigchld.

Yes, I could see why sharing SIGCHLD would be useful. I was thinking of
this when asking above when you want to have multiple watchers for the
same event, but this was the onl

Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Marc Lehmann wrote:
> Hi!
> 
> On tuesday, I sent mail about various problems with libevent and its
> current API as well as implementation. Unfortunately, the mail has not yet
> shown up, but fortunately, it has been superseded by this one :)
> 
> In that mail, I announced that I will work on the problems I encountered
> in libevent (many of which have been reported and discusssed earlier on
> this list). After analyzing libevent I decided that it wasn't fixable
> except by rewriting the core parts of it (the inability to have multiple
> watchers for the same file descriptor event turned out to be blocking for
> my applications, otherwise I wouldn't have started the effort in the first
> place...).
> 
> The results look promising so far: I additionally implemented a libevent
> compatibility layer and benchmarked both libraries using the benchmark
> program provided by libevent: http://libev.schmorp.de/bench.html
> 
> Here is an incomplete list of what I changed and added (see the full
> list at http://cvs.schmorp.de/libev/README, or the cvs repository at
> http://cvs.schmorp.de/libev/):
> 
> fixed or improved:
> 
> * multiple watchers can wait for the same event, there is no limitation
>   to one or two watchers for signals and io.

Could you give me an example of where that is important?

> * there is full support for fork, you can continue to use the event loop
>   in the parent and child (or just one of them), even with quirky backends
>   such as epoll.

Nice; seems like that's come up on the list several times.

> * there are two types of timers, based on real time differences and wall
>   clock time (cron-like). timers can also be repeating and be reset at
>   almost no cost (for idle timeouts used by many network servers). time jumps
>   get detected reliably in both directions with or without a monotonic clock.

(See my other mail about Linux's new timerfd facility.)

Nice; repeating and absolute timers have come up several times before, too.

> * timers are managed by a priority queue (O(1) for important operations
>   as opposed to O(log n) in libevent, also resulting in much simpler code).

In terms of concrete data types, you appear to have used a binary heap?
So by "important operations" you mean removal, correct? Insertion is
still O(log n)? The asymptotic behavior is no different, then, as
insertion happens at least as often as removal.

> * event watchers can be added and removed at any time (in libevent,
>   removing events that are pending can lead to crashes).

(They don't lead to crashes, as someone mentioned.)

> * different types of events use different watchers, so you don't have
>   to use an i/o event watcher for timeouts, and you can reset timers
>   seperately from other types of watchers. Also, watchers are much smaller
>   (even the libevent emulation watcher only has about 2/3 of the size of a
>   libevent watcher).

Nice; separate types can be nice for documentation purposes if nothing else.

> 
> * I added idle watchers, pid watchers and hook watchers into the event loop,
>   as is required for integration of other event-based libraries, without
>   having to force the use of some construct around event_loop.

Pardon my ignorance, but what are hook watchers?

pid watchers I assume to be a fancy SIGCHLD handler? That's a
potentially useful feature, but why would it require a construct around
event_loop?

> * the backends use a much simpler design. unlike in libevent, the code to
>   handle events is not duplicated for each backend, backends deal only
>   with file descriptor events and a single timeout value, everything else
>   is handled by the core, which also optimises state changes (the epoll
>   backend is 100 lines in libev, as opposed to >350 lines in libevent,
>   without suffering from its limitations).

Nice.

> As for compatibility, the actual libev api is very different to the
> libevent API (although the design is similar), but there is a emulation
> layer with a corresponding event.h file that supports the event library
> (but no evbuffer, evnds, evhttp etc.).

I think the API needs more hashing out. It is...different...but I'm not
sure it's necessarily better, and I don't like change for change's sake.
A few notes:

* what is the purpose of EV_COMMON? From first glance, I'm concerned
that it could not be used properly unless libev.so and all callers are
compiled with the same flags, which seems impractical if the library
ever gains wide use.

* on ev_once failure, you're calling the callback with EV_ERROR? Yuck.
That's quite surprising behavior, and I could see it leading to stack
overflows as each ev_once tries to issue another one.

* What's your use case for ev_loop_new() and ev_loop_default()'s bitmask
of allowed implementations?

* (again, just skimming) you're closing fds automatically on ENOMEM?
Ergh. That seems rather undesirable for many applications.

Cheers,
Scott
___
Libevent-users mailing list
Libevent-

Re: [Libevent-users] sensible thread-safe signal handling proposal

2007-11-04 Thread Scott Lamb
Steven Grimm wrote:
> On Nov 4, 2007, at 3:07 PM, Christopher Layne wrote:
>> The issue in itself is having multiple threads monitor the *same* fd
>> via any
>> kind of wait mechanism. It's short circuiting application layers, so
>> that a
>> thread (*any* thread in that pool) can immediately process new data. I
>> think
>> it would be much more structured, less complex (i.e. better
>> performance in
>> the long run anyways), and a cleaner design to have a set number (or even
>> 1) thread handle the "controller" task of tending to new network events,
>> push them onto a per-connection PDU queue, or pre-process in some form or
>> fashion, condsig, and let previously mentioned thread pool handle it
>> in an
>> ordered fashion.
> 
> You've just pretty accurately described my initial implementation of
> thread support in memcached. It worked, but it was both more
> CPU-intensive and had higher response latency (yes, I actually measured
> it) than the model I'm using now. The only practical downside of my
> current implementation is that when there is only one UDP packet waiting
> to be processed, some CPU time is wasted on the threads that don't end
> up winning the race to read it. But those threads were idle at that
> instant anyway (or they wouldn't have been in a position to wake up) so,
> according to my benchmarking, there doesn't turn out to be an impact on
> latency. And though I am wasting CPU cycles, my total CPU consumption
> still ends up being lower than passing messages around between threads.
> 
> It wasn't what I expected; I was fully confident at first that the
> thread-pool, work-queue model would be the way to go, since it's one
> I've implemented in many applications in the past. But the numbers said
> otherwise.

Thanks for the case study. To rephrase (hopefully correctly), you tried
these two models:

1) one thread polls and puts events on a queue; a bunch of other threads
pull from the queue. (resulted in high latency, and I'm not too
surprised...an extra context switch before handling any events.)

2) a bunch of threads read and handle events independently. (your
current model.)

Did you also tried the so-called "leader/follower" model, in which the
thread which does the polling handles the first event and puts the rest
on a queue; another thread takes over polling if otherwise idle while
the first thread is still working. My impression this was a widely
favored model, though I don't know the details of where each performs best.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] announcing libev, towards a faster and more featureful libevent

2007-11-04 Thread Scott Lamb
Marc Lehmann wrote:
>>> * there are two types of timers, based on real time differences and wall
>>>   clock time (cron-like). timers can also be repeating and be reset at
>>>   almost no cost (for idle timeouts used by many network servers). time 
>>> jumps
>>>   get detected reliably in both directions with or without a monotonic 
>>> clock.
>> But then they're not truly "real-time", no?
> 
> Within the limits of technology, they are:
> 
> - timers (based on monotonic time) will time out after "n" seconds (whatever
>   was configured), even if the date resets in between (libevent can do that
>   only for backward time jumps).
> 
> - periodicals will simply be rescheduled, if a periodic timer is scheduled
>   to fire "at" some point then it will not be affected by the time jump,
>   it will still fire at that point (its more complicated with periodic
>   timers scheduled to repeat, if you schedule a periodic timer to execute
>   on every minute than libev will try to schedule it to occur when time()
>   % 60 == 0, regardless of any time jumps.
> 
> Of course, detecting and correcting this cnanot be done completely
> reliable with sub-second precision (there is no API in posix to do that),
> but with a monotonic clock, libev should manage quite fine to detect even
> very small time jumps caused by ntpd.
> 
> (With no monotonic clock its a heuristic, obviously).

Have you seen the new Linux timerfd API? Where available, you can wait
for CLOCK_MONOTONIC and CLOCK_REALTIME events independently. Beats
heuristics, and detecting time jumps sound like introducing a lot of
extra timeouts. I'd hate to see libev(ent)? show up on PowerTOP after
just getting rid of the 5-second timeout.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Question: Library naming

2007-10-02 Thread Scott Lamb
Trond Norbye wrote:
> I thought that it was normal to name the libraries like 
> lib.so... (eg: libevent.so.1.3.4) and create
> symbolic links so the application may pick up the newest version of the
> library (with the correct ABI) without re-linking the application.

As did I, and I've wondered about this for a while.

> 
> Is there a good reason for not doing so?

Nick, have you given any thought to this? I'm surprised to see your
arguments about preserving compatibility considering that each client
application needs to be relinked to pick up libevent bugfixes, and many
versions of libevent kept around on systems where they haven't been.
libevent's APIs (existing functions' signatures + "struct event" layout)
changes infrequently enough that I think most releases could just be a
minor version bump.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] Add autoconf/make functionality for --disable-dns, --disable-http, and --disable-bevents

2007-10-02 Thread Scott Lamb
Chris Brody-GMail wrote:
> I would like to suggest another idea, to automatically build both a
> "full" libevent library and a set of separated libevent parts, until
> the next major release.

+1

I think the -levent-core -lev-http approach makes sense, but (quoting
Nick Mathewson's email):

> I'm no expert on cross-platform dynamic linkers, but is it feasible
> (with libtool or otherwise) to arrange things so that we can split
> libevent into separate libraries (libevent-core, libevent-http, etc),
> while at the same time ensuring that we don't break old code that
> searches for a "libevent" library with all the current libevent APIs?

IIRC, Chris Brody's suggestion is the only way to do that, as library
dependencies are not transitive in some situations (static libraries,
and dynamic libraries some platforms).


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] Add autoconf/make functionality for --disable-dns, --disable-http, and --disable-bevents

2007-10-02 Thread Scott Lamb
Nick Mathewson wrote:
> On Tue, Oct 02, 2007 at 09:35:48AM +0200, Robert Iakobashvili wrote:
>  [...]
>> libcurl has developed a good API for its integration with libevent.
>> libcurl project also maintains and develops a very good asynchronous DNS
>> client library, called c-ares (a clone of ares).
>>
>> Could it be a better path to concentrate the community efforts on
>> integration of c-ares and libcurl with libevent and to assist better
>> to applications?
> 
> I would love somebody to get c-ares working right with libevent.  I
> don't think this is a matter of "concentrating the community efforts",
> however: I think it's a matter of somebody stepping up to contribute
> the right patch to c-ares.
> 
> The last time I checked, the main problems preventing c-ares from
> working optimally with libevent were:
>   o C-ares had functions to fetch a list of sockets that needed
> to be read and written, but no way to make a callback happen when
> that list changes.  This is fine for select() and poll(), but
> Libevent, on the other hand, wants to be told about _changes_ in
> socket state via event_add and event_del.
> 
> Fixing this is probably a matter of adding a callback facility to
> c-ares.

It already exists:

struct ares_options options;

...
options.sock_state_cb = foo;
...
... = ares_init_options(..., &options, ...|ARES_OPT_SOCK_STATE_CB);

>   o The only way to tell c-ares about readable/writable sockets was
> via a function, ares_process(), that took an fd_set.  This is
> suboptimal because 1) Libevent wants to alert applications about
> one socket at a time, and 2) Libevent is designed for situations
> where there are thousands of sockets, and making an fd_set with
> thousands of elements gives awful performance.
> 
> Fixing this is probably a matter of adding an alternate way to
> invoke functionality of ares_process().

Also exists:

void ares_process_fd(ares_channel channel, ares_socket_t read_fd,
 ares_socket_t write_fd);

> 
> Of course, stuff may have changed since then; these problems may be
> solved.

Yup.

> 
> (I, _personally_, don't think I could use c-ares for my needs, since I
> need DNS server support as well as client support, and I'm under the
> impression that c-ares only provides the latter.  But the more
> libraries that support libevent, the better.)
> 
> yrs,
> 
> 
> 
> 
> ___
> 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


Re: [Libevent-users] multiple read events triggered

2007-10-02 Thread Scott Lamb

Matt Pearson wrote:

Please reply to the whole list in the future.

epoll actually supports (according to its man page) both this style of
notification and edge-triggered, where it tells you when a read is
first available and it's up to you to keep reading until read() fails
with errno = EAGAIN.  However, since not all notification mechanisms
support this kind of behavior, libevent uses the one that gives
consistent behavior across backends.  Besides, in many situations,
this kind of behavior is more useful.


I remember seeing a while ago a patch that would optionally use the 
other behavior.


Not sure if it ever made it to this list, but google finds it elsewhere:

https://webmail.iro.umontreal.ca/pipermail/gambit-list/2005-August/000367.html

if "event_abilities() & EV_ABILITY_EDGE" is true, you could use 
EV_READ|EV_WRITE|EV_PERSIST|EV_EDGE or the like.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Undefined reference

2007-09-20 Thread Scott Lamb

Marcelo Estanislau Geyer wrote:

Hi,

I'm development small program in C++ on Linux (Fedora 7 and Kdevelop).
When compiling the program, is appearing the following message:

undefined reference to `event_init'

I have add header event.h, but I am with difficulties to work with this 
library due to these errors.


The header is used at compile-time. 'undefined reference' is a link-time 
error. You need to link in -levent as well.



Thanks,

Marcelo Estanislau
Brazil.


Receba GRÁTIS as últimas novidades do esporte direto no seu Messenger! 
Assine já! 






___
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


[Libevent-users] event_base_loop_break()?

2007-09-18 Thread Scott Lamb

While playing with pyevent, I saw this code:

def abort():
"""Abort event dispatch loop."""
cdef extern int event_gotsig
cdef extern int (*event_sigcb)()
event_sigcb = __event_sigcb
event_gotsig = 1

This is used in exception handling - if a callback throws an exception, 
it does this to propogate the exception through immediately (breaking 
out of the loop without running any more callbacks).


This off-label use of a deprecated libevent interface is confusing, and 
I suspect it can interact badly with the more modern signal handling 
interface.


I propose instead that libevent have a event_base_loop_break() and 
event_loop_break(). (Or whatever you want them called.) They'd differ 
from event_{base_,}loop_exit() in that they would *immediately* abort 
the loop without finishing the iteration (i.e., sooner than 
event_base_loop_exit({.tv_sec=0, .tv_usec=0})). They'd be analogous to 
the C "break;" statement. Like event_loop_exit(), the next dispatch 
would be unaffected.


Feelings? I'd be happy to work up a patch and unit test.

Best regards,
Scott

[1] - Well, not quite, because there's a bug. 
<http://code.google.com/p/pyevent/issues/detail?id=6> But it's clearly 
intended to, and with a small patch it does.


--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Newbie question about threads

2007-08-06 Thread Scott Lamb

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
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[PATCH] Re: [Libevent-users] rtsig doesn't compile - remove?

2007-08-04 Thread Scott Lamb
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
>From a5d264a55153e029e58eebb60840f0ed17a81071 Mon Sep 17 00:00:00 2001
From: Scott Lamb <[EMAIL PROTECTED]>
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..000
--- a/libevent/rtsig.c
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * Copyright (c) 2006 Mathew Mills <[EMAIL PROTECTED]>
- * All rights reserved

Re: [Libevent-users] [PATCHES] use monotonic clock & infinite timeouts

2007-08-04 Thread Scott Lamb
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: 0x0034
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  0x4bbf in http_post_test () at regress_http.c:468
#6  0x554a in http_suite () at regress_http.c:728
#7  0x3f12 in main (argc=1, argv=0xb3ac) at regress.c:1052

Here's the relevant bit from frame #1:

521if (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
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] initialize ev_res

2007-08-04 Thread Scott Lamb
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:
>>>>
>>>> 632if ((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:

[EMAIL PROTECTED] ~]$ 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;
}
[EMAIL PROTECTED] ~]$ 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
[EMAIL PROTECTED] ~]$ 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.

[EMAIL PROTECTED] ~]$ valgrind --version
valgrind-3.2.1
[EMAIL PROTECTED] ~]$ gcc -Wall -O2 test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate...
==24325== Conditional jump or move depends on uninitialised value(s)
==24325==at 0x400504: main (in /home/slamb/test)
...
[EMAIL PROTECTED] ~]$ gcc -Wall test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...



You'll notice the same thing does not happen on a 32-bit machine.

[EMAIL PROTECTED] ~]$ uname -a
Linux spiff-centos5 2.6.23-rc1 #8 SMP Fri Jul 27 21:02:53 PDT 2007 i686
i686 i386 GNU/Linux
[EMAIL PROTECTED] ~]$ 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.

[EMAIL PROTECTED] ~]$ valgrind --version
valgrind-3.2.1
[EMAIL PROTECTED] ~]$ gcc -Wall -O2 test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...
[EMAIL PROTECTED] ~]$ gcc -Wall test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...

> I still do not bel

Re: [Libevent-users] [PATCH] initialize ev_res

2007-08-04 Thread Scott Lamb

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:

632if ((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
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCHES] use monotonic clock & infinite timeouts

2007-07-25 Thread Scott Lamb
Scott Lamb wrote:
> libevent's monotonic clock detection is currently broken on all
> platforms. The first attached patch fixes it. The second takes advantage
> of it to remove the 5-second idle timeout where possible.

Actually, I don't think I understand the purpose of this timeout at all.
I had thought it was to make some effort to adjust the timeout values if
the system clock gets set backwards (related to timeout_correct()). But
for that to make any sense, it'd have to be a limit on the time to wait
when there are longer timeouts. Instead, it's a time to wait when
there's no timeout scheduled at all.

I don't think it accomplishes anything. Maybe the default timeout should
be removed entirely, not just if a monotonic clock is available?

Best regards,
Scott

-- 
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCHES] use monotonic clock & infinite timeouts

2007-07-25 Thread Scott Lamb
Scott Lamb wrote:
> libevent's monotonic clock detection is currently broken on all
> platforms. The first attached patch fixes it. The second takes advantage
> of it to remove the 5-second idle timeout where possible. This is
> starting to become a big deal on Linux, where they've removed ticks from
> the kernel and are now using tools (PowerTOP) to remove unnecessary
> wakeups from userspace.  This effort is greatly extending my battery life.

In fact, I just saw RedHat has a bug open specifically about libevent's
5-second timer.

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=204990
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] [PATCHES] use monotonic clock & infinite timeouts

2007-07-25 Thread Scott Lamb
libevent's monotonic clock detection is currently broken on all
platforms. The first attached patch fixes it. The second takes advantage
of it to remove the 5-second idle timeout where possible. This is
starting to become a big deal on Linux, where they've removed ticks from
the kernel and are now using tools (PowerTOP) to remove unnecessary
wakeups from userspace.  This effort is greatly extending my battery life.

I've successfully run test/test.sh with these patches on OS X 10.4
(which does not have clock_gettime()) and Linux 2.6 (which does). So
it's been tested with all event methods except devpoll (sorry, no
Solaris machine handy at the moment) and rtsig (which won't compile with
or without these patches).

On Linux, I've verified with strace and PowerTOP that it's actually
using CLOCK_MONOTONIC and infinite timeouts.

Best regards,
Scott

-- 
Scott Lamb <http://www.slamb.org/>
>From bbf1036054ba1546682c6c130d4b77e2ee95b264 Mon Sep 17 00:00:00 2001
From: Scott Lamb <[EMAIL PROTECTED]>
Date: Wed, 25 Jul 2007 12:06:17 -0700
Subject: [PATCH] use CLOCK_MONOTONIC where available

* look for clock_gettime in librt, which is used on Linux
* remove check for HAVE_CLOCK_MONOTONIC (there was no configure glue)
* detect at runtime - useful if a libevent-based program is run on an older
  kernel than it is compiled on

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---
 libevent/configure.in |1 +
 libevent/event.c  |   37 +
 2 files changed, 26 insertions(+), 12 deletions(-)
 mode change 100644 => 100755 libevent/autogen.sh

diff --git a/libevent/autogen.sh b/libevent/autogen.sh
old mode 100644
new mode 100755
diff --git a/libevent/configure.in b/libevent/configure.in
index 507090b..1acfa84 100644
--- a/libevent/configure.in
+++ b/libevent/configure.in
@@ -37,6 +37,7 @@ AC_ARG_WITH(rtsig,
 dnl Checks for libraries.
 AC_CHECK_LIB(socket, socket)
 AC_CHECK_LIB(resolv, inet_aton)
+AC_CHECK_LIB(rt, clock_gettime)
 
 dnl Checks for header files.
 AC_HEADER_STDC
diff --git a/libevent/event.c b/libevent/event.c
index 2048157..fc54d23 100644
--- a/libevent/event.c
+++ b/libevent/event.c
@@ -51,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "event.h"
 #include "event-internal.h"
@@ -113,6 +114,7 @@ const struct eventop *eventops[] = {
 /* Global state */
 struct event_base *current_base = NULL;
 extern struct event_base *evsignal_base;
+static int use_monotonic;
 
 /* Handle signals - This is a deprecated interface */
 int (*event_sigcb)(void);  /* Signal callback when gotsig is set */
@@ -143,25 +145,34 @@ compare(struct event *a, struct event *b)
return (0);
 }
 
+static void
+detect_monotonic(void)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+   struct timespec ts;
+
+   if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+   use_monotonic = 1;
+#endif
+}
+
 static int
 gettime(struct timeval *tp)
 {
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec ts;
 
-#ifdef HAVE_CLOCK_MONOTONIC  
-   if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
-#else
-   if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
-#endif
-   return (-1);
-   tp->tv_sec = ts.tv_sec;
-   tp->tv_usec = ts.tv_nsec / 1000;
-#else
-   gettimeofday(tp, NULL);
+   if (use_monotonic) {
+   if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+   return (-1);
+
+   tp->tv_sec = ts.tv_sec;
+   tp->tv_usec = ts.tv_nsec / 1000;
+   return (0);
+   }
 #endif
 
-   return (0);
+   return (gettimeofday(tp, NULL));
 }
 
 RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare);
@@ -180,6 +191,8 @@ event_init(void)
 
event_sigcb = NULL;
event_gotsig = 0;
+
+   detect_monotonic();
gettime(&base->event_tv);
    
    RB_INIT(&base->timetree);
-- 
1.5.3.GIT

>From d7f9e3b60c9bf5b1a9daf9cc9ec027d16c944816 Mon Sep 17 00:00:00 2001
From: Scott Lamb <[EMAIL PROTECTED]>
Date: Wed, 25 Jul 2007 11:40:16 -0700
Subject: [PATCH] remove unnecessary wakeups on idle

libevent wakes up every 5 seconds to check if the clock has gone backwards.
On platforms with CLOCK_MONOTONIC, this is unnecessary. With the new Linux
effort to reduce wakeups for laptops (e.g., PowerTOP) and libevent starting
to show up in standard system tools (e.g., rpc.idmapd), it's better to
avoid this where possible.

Signed-off-by: Scott Lamb <[EMAIL PROTECTED]>
---
 libevent/devpoll.c |5 +++--
 libevent/epoll.c   |6 --
 libevent/event.c   |   51 +++
 libevent/kqueue.c  |9 ++---
 libevent/poll.c|9 ++---
 libevent/rtsig.c   |   36 --

[Libevent-users] rtsig doesn't compile - remove?

2007-07-24 Thread Scott Lamb
While composing a patch (more on that later), I noticed that rtsig.c
doesn't even compile. In particular,

* it uses signalqueue, which was removed in revision 351
* it has an unnamed function argument, which isn't legal C! (only C++)
* it uses , which of course is Linux-only
* it uses _syscall0, which hasn't existed for quite some time

Niels, how would you feel about removing rtsig entirely? It's the most
complex mechanism (985 lines...others range from epoll @ 364 lines to
kqueue at 413 lines) and totally obsolete/unmaintained. Modern Linux
people are all using epoll_wait(), and older ones must be content with
select()/poll() or they would have complained about rtsig's status.

Best regards,
Scott

-- 
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] [PATCH] initialize ev_res

2007-07-19 Thread Scott Lamb
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:

632if ((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.

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.

Best regards,
Scott

-- 
Scott Lamb <http://www.slamb.org/>
Avoid valgrind warning

==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)

Index: event.c
===
--- event.c (revision 369)
+++ event.c (working copy)
@@ -530,6 +530,7 @@
ev->ev_arg = arg;
ev->ev_fd = fd;
ev->ev_events = events;
+ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
ev->ev_ncalls = 0;
ev->ev_pncalls = NULL;
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Solaris 10 Sun Studio 11 & libevent 1.3b

2007-06-18 Thread Scott Lamb

William Pool wrote:

"event_tagging.c", line 153: syntax error before or at: decode_int_internal
"event_tagging.c", line 154: warning: old-style declaration or incorrect 
type for: decode_int_internal


I'd guess it's tripping on the "inline":

event_tagging.c
152: static int inline
153: decode_int_internal(u_int32_t *pnumber, struct evbuffer *evbuf, int 
dodrain)

154: {

Take a look through the list archives - Jan Kneschke posted a bunch of 
patches on the 14th for compiling on Solaris, subject line "compile 
patches for non-gcc".

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Bug in signal.c

2007-05-28 Thread Scott Lamb


On May 28, 2007, at 8:28 AM, Jesse Keller wrote:


Just implemented libevent in a new program using the cool eventxx C++
wrapper.  Anyway, I decided to track down the event_base_free bug a
little more.  Here's the original bug and patch.

http://monkeymail.org/archives/libevent-users/2006-April/000141.html

Seems that we don't need to go through all that effort of fixing the
symptom, it's just that the internal event between the signal handler
and the dispatcher is never deleted.

Here's the patch that fixes the problem for me (versus the 1.3b  
release)



--- signal.c2007-03-03 23:05:07.0 -0500
+++ signal.c.new2007-05-28 11:10:57.0 -0400
@@ -143,6 +143,11 @@
int evsignal;

evsignal = EVENT_SIGNAL(ev);
+
+   if (ev_signal_added) {
+   ev_signal_added = 0;
+   event_del(&ev_signal);
+   }

return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *) 
SIG_DFL,

NULL));
 }


But ev_signal is for the pipe used to wake up on receipt of *any*  
signal. Consider this code snippet:


signal_set(&ev1, SIGUSR1, signal_cb, NULL);
event_add(&ev1, NULL);
signal_set(&ev2, SIGUSR2, signal_cb, NULL);
event_add(&ev2, NULL);
event_del(&ev2);

raise(SIGUSR1);
event_dispatch(EVLOOP_ONCE);

without your change, the dispatch would return immediately. With your  
change, it would wait until timeout.


--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] How do i make a multi-threaded libevent server?

2007-05-11 Thread Scott Lamb

On May 11, 2007, at 8:46 AM, Niels Provos wrote:

I would really like to see measurements on that.   Do you have any
graphs that show the performance differences between single-threaded
and multi-threaded implementation?


Speaking of which, I've been meaning to benchmark some single- 
threaded vs. multi-threaded libevent approaches for a while, but  
haven't really gotten around to working up appropriate benchmark  
software.


But it occurs to me...you have those nice graphs on the libevent  
webpage of different implementations. What'd you use to make that?  
Maybe it could be adapted pretty easily.


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] fixes for better Solaris support

2007-05-04 Thread Scott Lamb

On May 3, 2007, at 8:18 PM, Harry Kao wrote:

  - Changed u_intX_t to uintX_t.  This was changed in event_rpcgen.py
as well.  I don't use that script so I hope this was the right
thing to do...


This sort of question is why it would be nice to have a buildbot  
installation with a bunch of different platforms. You'd just try the  
change, see if it breaks anywhere else.


Frustrating - I had one set up, but first there were a bunch of  
memory limit problems with my server, then when I got that fixed, I  
lost most of the platforms because sourceforge shut down their  
compile farm. I've done the work to configure it for libevent as well  
as a project of my own, but it's not doing much good now for lack of  
machines.


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] multiple calls of event_dispatch()

2007-02-26 Thread Scott Lamb


On Feb 26, 2007, at 2:57 PM, Christian Ress wrote:


Hello,

I stumbled across libevent and it seems to fit my needs very well.
However, I wonder if this is side-effect free:

second_cb(..) { .. }
first_cb(..) {
  ..
  struct event newev;
  evtimer_set(&newev, second_cb, NULL);
  event_base_set(ev_base, &newev);
  event_add(&newev, &tv);

  event_base_dispatch(ev_base);
}

main() {
  ..
  ev_base = event_init();
  evtimer_set(ev, first_cb, NULL);
  event_add(ev, &tv);

  event_base_dispatch(ev_base);
}

The point of this is creating new events 'on demand', but since I'm  
calling event_dispatch when being called by event_loop, I wonder if  
this might lead to recursion issues or similar bad behaviour.


I hope someone can clarify this :)


First, keep in mind something that tripped up me when I first started  
using libevent - the "struct event" you pass to event_add is not  
duplicated, but rather directly linked into the event_base's queues.  
So if it's a timeout, it needs to live until it fires (or forever  
with EV_PERSIST) or you manually call event_del(). There are a lot of  
reasons that might not happen in the next invocation of  
event_base_dispatch(), so this code seems dangerous.


And second...while I don't see anything off-hand in libevent that  
would break based on this recursion, I don't think it was intended to  
be used that way, and you always risk stack overflows if you don't  
have a way to bound your recursion.


You can create new events 'on demand' with event_once. Which isn't  
magic - it just internally allocates a new struct event on the heap  
that adds a callback which - after calling your callback - frees the  
struct event. You could accomplish the same thing yourself:


void
first_cb(int fd, short events, void *arg)
{
struct event *newev;
int res;

...

newev = malloc(sizeof(struct event));
...newev == NULL error handling goes here...
evtimer_set(newev, ...);
res = event_add(&newev, &tv);
...event_add error handling goes here...
}

void
second_cb(int fd, short events, void *arg)
{
struct event *myev = arg;

...
free(myev);
}

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Sigprocmask vs pthread_sigprocmask

2007-02-24 Thread Scott Lamb


On Feb 24, 2007, at 12:49 PM, Niels Provos wrote:


 I know that
it's difficult to get complete coverage, but some tests for each new
change are a very good practice.


Well, at least the test_immediatesignal() fails with the old code and  
passes with the new code.


I would love to get coverage of the race condition as well...but I  
don't have a good way to do it. I had this same discussion with the  
Twisted people not too long ago. I kind of think full coverage is a  
good goal to shoot for, but essentially impossible to achieve.


--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Sigprocmask vs pthread_sigprocmask

2007-02-24 Thread Scott Lamb


On Feb 22, 2007, at 6:32 PM, Niels Provos wrote:


Do you have an addition to the regression test that would allow me to
verify that the new code works as intended?   If not, it would be most
appreciated :-)


Happy Weekend, everyone. Looking at this again.

There are two regression tests for this now:

* test_simplesignal() tests a signal delivered while within select()/ 
poll()/kevent()/epoll()/whatever.
* test_immediatesignal() tests a signal delivered between signal_add 
() and event_loop().


But you're referring to something more...proving that there would  
have been an evsignal_process() race if not for the reordering,  
right? That's hard to do through regression tests. I can think of  
only a couple ways to do that:


(1) loop trying it many times, scheduling later delivery with alarms  
or through an additional thread (tests would depend on pthreads).  
Probably have to add some instrumentation to evsignal_process() to  
make it sleep at particular times to make it likely enough to happen  
on demand.


(2) use debugging mechanisms to step through and deliver the signal  
at a particular time. I actually have done this programmatically  
before when proving a signal-handling library [*], but it was a lot  
of code and not exactly the most portable. Maybe it could be done  
more easily with gdb and expect, on at least gdb platforms.


Would it help if I showed you a way to test it by hand?

I've attached a simple test program that registers a handler for  
SIGUSR1 and SIGUSR2 which simply notes the signal was received. You  
can see the races I mention with gdb as follows:


$ gcc -Wall sigtest.c -o sigtest -L.libs -levent
$ LD_LIBRARY_PATH=.libs gdb ./sigtest
...
(gdb) break evsignal_process
Function "evsignal_process" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (evsignal_process) pending.
(gdb) run
Starting program: /home/slamb/svn/libevent/sigtest
(no debugging symbols found)
<<>>
Breakpoint 2 at 0x2aabf4a0: file signal.c, line 165.
Pending breakpoint "evsignal_process" resolved

Program received signal SIGINT, Interrupt.
0x00318a4cd9d3 in __epoll_wait_nocancel () from /lib64/libc.so.6
(gdb) signal SIGUSR1
Breakpoint 2, evsignal_process () at signal.c:165 (my line numbers  
are off because I've #ifdefed the two code blocks)

<<>>
(gdb) n
179 memset(evsigcaught, 0, sizeof(evsigcaught));
(gdb) signal SIGUSR2
Continuing with signal SIGUSR2.
Received signal 10

Here you can see that it only acknowledged receipt of SIGUSR1;  
SIGUSR2 was lost.


If you do the same thing at any point in my modified evsignal_process 
(), you find instead:


(gdb) signal SIGUSR2
Continuing with signal SIGUSR2.
Received signal 10

Breakpoint 2, evsignal_process () at signal.c:165
165 {
(gdb) c
Continuing.
Received signal 12

[*] http://www.slamb.org/svn/repos/trunk/projects/sigsafe/tests/ 
race_checker/


--
Scott Lamb <http://www.slamb.org/>



sigtest.c
Description: Binary data
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Sigprocmask vs pthread_sigprocmask

2007-02-22 Thread Scott Lamb


On Feb 22, 2007, at 6:32 PM, Niels Provos wrote:


Do you have an addition to the regression test that would allow me to
verify that the new code works as intended?   If not, it would be most
appreciated :-)


There is one that verifies the quickly received signal case. Are you  
talking about the race condition I describe? In that case, no...I  
could try something that pounds on it in a loop for a bit or  
something, if you like.


Also realized I sent an older version of the patch just now...newer  
one attached. (Why can I never send a patch to a mailing list  
correctly the first time? It's a bizarre handicap.)




event-signal.patch
Description: Binary data
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Sigprocmask vs pthread_sigprocmask

2007-02-22 Thread Scott Lamb


On Feb 21, 2007, at 1:29 AM, William Ahern wrote:


On Wed, Feb 21, 2007 at 03:44:58AM -0500, Nick Mathewson wrote:

libevent, "I'm going to use pthreads; use pthread_sigmask()  
instead of

sigprocmask()."  I don't know what that interface should be, but the
corresponding code should be pretty simple to write.


Probably should be a [global] function pointer, since an autoconf  
check

doesn't address the linking issue.


What about just never using sigprocmask() or pthread_sigmask()? The  
patch I sent to the list a while back fixes two bugs:


* prevents Anton Povarov's reported race in which a signal delivered  
quickly after event_signal_add() isn't handled correctly

* avoids sigprocmask(), which is not pthread-safe.

There are still several caveats with threads. Ignoring the complex  
idea of sharing an event_base between threads (need still has to be  
proven...I've been way too busy with other things to run the  
benchmarks I've been wanting to), these ones remain:


2. If you forget event_base_set on an event, it's associated with the  
latest base created. This will probably work most of the time. It'd  
be much less confusing if it consistently broke.


3. Each new base created leaks the existing ev_signal_pair descriptors.

4. Signals are delivered to whatever event loop happens to see them  
first.


6. You can't destroy an event_base.

My old patch and notes are below.

This patch does not get rid of ncalls, which I'm also thinking of  
doing, as I mentioned in an earlier message to the list.


devpoll.c  |   15 +++
epoll.c|   15 +++
evport.c   |   17 +++--
evsignal.h |8 ++
poll.c |   15 +++
select.c   |   14 +++---
signal.c   |   74 +++ 
+-

test/regress.c |   32 
8 files changed, 76 insertions(+), 114 deletions(-)

There's one subtlety to it. With my change, evsignal_process() runs  
with signals unblocked, so timing is critical. The original code is  
then racy:


TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
ncalls = evsigcaught[EVENT_SIGNAL(ev)]; <-- point A
if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
}
}

memset(evsigcaught, 0, sizeof(evsigcaught));<-- point B
evsignal_caught = 0;<-- point C

For any signal that is not already pending (ncalls == 0 when reaching  
its point A), if it arrives between then and its ncalls being cleared  
in point B, it will be lost. If it arrives after then but before  
evsignal_caught in point C, it will be arbitrarily delayed (until  
another signal comes along to set 	evsignal_caught).


I solved this by

* moving the evsignal_caught to before checking the individual  
signals for delivery (but after evsignal_caught is checked itself, in  
a different function).
* setting "evsigcaught[x] = 0" only when we are setting that signal  
active.


--
Scott Lamb <http://www.slamb.org/>



event-signal.patch
Description: Binary data


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] event_queue_remove spent too much time

2007-02-10 Thread Scott Lamb

On Feb 10, 2007, at 9:29 AM, Person wrote:

Hi,
Is it normally that high cost function call issue about  
event_queue_remove()?
I profiles my program with gprof. I found the most spent time  
function call is event_queue_remove().

However, I only remove events when connection is closed (conn_drop()).
There are two types events with flag EV_WRITE and (EV_READ |  
EV_PERSIST) in my program. And, there are about 250 connections and  
250*2 events (read and write fd).


Well, event_queue_remove() is getting called in three different ways.  
From least to most often,


* Twice from each conn_drop(), on the EVLIST_INSERTED queue.
* Once implicitly on each write callback on the EVLIST_INSERTED  
queue, since you're not using EV_PERSIST on writes

* Once on each callback on the EVLIST_ACTIVE queue.

It just removes the event from a doubly-linked list in O(1) time. So  
even with so many calls, I'm surprised to see that 8.65%. A few  
thoughts:


* If this trivial function is so high up on the CPU usage, is your  
program not CPU-bound at all?


* Does gprof add overhead to each function call? I don't remember how  
it works, but if it does, this might unfairly penalize quick but  
often-called functions like event_queue_remove(). Seems like  
event_queue_insert() should be in the same boat, though...it gets  
called as often and does a very similar thing.


* Maybe event_queue_remove() is getting a disproportionate number of  
cache misses and waiting for memory access? Does "valgrind -- 
tool=cachegrind" give this kind of information?


Cheers,
Scott

--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] looking for a swig interface for libevent

2007-01-04 Thread Scott Lamb


On Dec 25, 2006, at 10:16 AM, [EMAIL PROTECTED] wrote:


I'm python developer and using libevent via pyevent (pyrex).
But, is there any one having a Swig interface for libevent ?


Why would you want one? If pyevent works, what makes you think a swig  
wrapped would be better? I haven't been impressed with swig, and  
apparently Guido van Rossum hasn't either:


"I've yet to see an extension module using SWIG that doesn't make me  
think it was a mistake to use SWIG instead of manually written  
wrappers. The extra time paid upfront to create hand-crafted wrappers  
is gained back hundredfold by time saved debugging the SWIG-generated  
code later."


http://www.artima.com/weblogs/viewpost.jsp?thread=95863

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] bug with 1.2

2006-11-14 Thread Scott Lamb

On Nov 1, 2006, at 12:31 AM, Phil Oleson wrote:

  /* Setup the initial game_iteration pass */
  gettimeofday(&tvt, (struct timezone *) 0);
  timeradd(&tvt, &sleep_tv, &tvt);

  evtimer_set(&tev, iteration, &tev);
  evtimer_add(&tev, &tvt);


libevent takes relative times; you're passing in absolute. I have no  
idea why this worked for you with versions prior to 1.2.


Cheers,
Scott

--
Scott Lamb <http://www.slamb.org/>
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] buildbot is running

2006-11-13 Thread Scott Lamb

On Nov 11, 2006, at 4:55 PM, Scott Lamb wrote:
Looks like they're all problems with my setup rather than libevent.  
I'll look more later. Since the ones with automake problems are all  
sourceforge compile farm machines I connect to from remotely, I  
might just run autoreconf locally before rsyncing the files over.


I switched it to run the automake stuff locally, and there are new  
errors:


* Solaris 9 doesn't have "stdint.h", so both sparc-sunos and x86- 
sunos fail. configure is checking for this, but apparently the result  
isn't used.

* OpenBSD 3.8 doesn't, either, so x86-openbsd fails.
* glibc 2.3.2 on alpha doesn't have "va_copy", so alpha-linux1 fails.

These systems are all about a generation old. I just threw in  
everything I had access to, and these are the only Solaris, OpenBSD,  
and Linux/alpha systems I could find. If they're too old for you to  
care about, just say the word and I'll pull them. Otherwise, I guess  
they need a little autoconf magic.


By the way, if anyone does have the ability to set up a new SSH login  
on other weird platforms, I'd greatly appreciate it. sigsafe used to  
support FreeBSD/alpha, Linux/alpha (my test code requires a newer  
kernel than sourceforge's machine has), Linux/ia64, HP-UX/ia64, HP-UX/ 
parisc, and Tru64/alpha. HP seems to have shut down their Test Drive  
program, so I can't develop for these anymore.


Cheers,
Scott

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] evbuffer issues on GNU/Linux amd64

2006-11-11 Thread Scott Lamb

On Nov 9, 2006, at 6:17 PM, Niels Provos wrote:

I submitted a fix along these lines to subversion.  Please, check it
out and see if you can reproduce problems on amd64.  I don't have
access to such a system.


Oh, buildbot also lets you force a build of a particular revision. So  
you should be able to force a build of 250 and see it fail, then 251  
and see it pass.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] evbuffer issues on GNU/Linux amd64

2006-11-09 Thread Scott Lamb

On Nov 9, 2006, at 6:17 PM, Niels Provos wrote:

I submitted a fix along these lines to subversion.  Please, check it
out and see if you can reproduce problems on amd64.  I don't have
access to such a system.


Oh, by the way. I've been getting into buildbot lately. Are you  
interested in having a buildbot setup that automatically compiles and  
regresses every Subversion checkin? I'm thinking of setting one up  
for sigsafe, and doing other projects is not much more trouble.  
Certainly I'll have Linux/x86 and Linux/x86_64 buildslaves. Probably  
Darwin/ppc64. Hopefully some more exotic ones, too.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] evbuffer issues on GNU/Linux amd64

2006-11-09 Thread Scott Lamb

On Nov 9, 2006, at 6:17 PM, Niels Provos wrote:

I submitted a fix along these lines to subversion.  Please, check it
out and see if you can reproduce problems on amd64.  I don't have
access to such a system.


I can confirm the fix. It crashed in this spot for me before; I  
didn't know why. Revision 252 works.


Best regards,
Scott
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] questions about bufferevent

2006-10-30 Thread Scott Lamb
On Oct 30, 2006, at 6:11 PM, cwinl wrote:I doubt your problems are because of incorrect use of  bufferevent_write. I bet one of the following things is happening:  i agree with you . i also suspect  my usage of  bufferevent_write. can you illustrate  an  example ? Afraid not; I've never actually used the bufferevent stuff. Maybe someone else can.___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] questions about bufferevent

2006-10-30 Thread Scott Lamb

On Oct 30, 2006, at 1:11 AM, cwinl wrote:

hi,all
i am a newbie to libevent.
i use libevent to build my application's network framework. it works
well. but  there are still some questions about it.
data reading from network work very well.
but data i want to write to network are not very reliable  when
about 200 clients connect to my server.
i write data to client using method "bufferevent_write" , but
sometimes clients get  the data after 7 or 8 seconds.
here are my main code, any suggestion are regarded. thank you!


I doubt your problems are because of incorrect use of  
bufferevent_write. I bet one of the following things is happening:


1) You're only getting around to each socket every 7 or 8 seconds.  
Try adding some instrumentation to see where the time is going.  
(gettimeofday() for wall-clock time, getrusage() for CPU time.) It's  
probably in "my_own_biz_code()".


2) You've saturated your network connection. How fast can you send  
data, and how fast are you sending data? On Linux, "sar -n DEV 1000  
1" will show you bandwidth utilization every second (for 1000 seconds).


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] event_dispatch() error with device tun0

2006-10-27 Thread Scott Lamb

On 26 Oct 2006, at 19:13, Sachin K wrote:

Hi all,
I am trying to capture read events on tun0 device on freeBSD 5.5 using
libevent library v1.2. But the event_dispatch() function returns with
an error "Operation not supported by device".

Is /dev/tun0 device supported by libevent 1.2?


libevent doesn't do anything differently than you'd do by directly  
using kqueue(), poll(), or select() system calls. I know at least  
select() works on FreeBSD's tun0 device, since tinc uses it.


You might try:

* looking through tinc's code for some device-specific setup you're  
missing

* checking what actual system called failed with ktrace
* testing each mechanism:

$ EVENT_SHOW_METHOD= ./test
(should say kqueue)

$ EVENT_SHOW_METHOD= EVENT_NOKQUEUE= ./test
(should say poll)

$ EVENT_SHOW_METHOD= EVENT_NOKQUEUE= EVENT_NOPOLL= ./test
    (should say select)

--
Scott Lamb <http://www.slamb.org/>

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] Patches and complaints

2006-10-18 Thread Scott Lamb

Niels,

I sent a few patches to the list and got no reply from you - I think  
you were on vacation. Here they are again, slightly cleaned up. One- 
line summary here; full description at the top of the attached files.


* event-once-leak.patch - fixes event_once() leak on event_add()  
failure.

* event-poll-leak.patch - fixes realloc() leak in poll() code
* event-signal.patch - fixes a SIGCHLD problem reported by Anton  
Povarov <[EMAIL PROTECTED]>


test/regress as of libevent 1.2 segfaults for me (Linux/x86_64) in  
the evbuffer stuff. I haven't done much to diagnose, since I don't  
use it. But here's something. After turning off "-O" and turning on  
USE_DEBUG:


$ LD_LIBRARY_PATH=.libs gdb test/.libs/regress
...
(gdb) run
...
Evbuffer:
Program received signal SIGSEGV, Segmentation fault.
0x003f12173c90 in ?? () from /lib64/libc.so.6
(gdb) bt
#0  0x003f12173c90 in ?? () from /lib64/libc.so.6
#1  0x003f1214488b in _IO_vfprintf_internal (s=0x7fff44567930,  
format=Variable "format" is not available.

) at vfprintf.c:1559
#2  0x003f121652fa in _IO_vsnprintf (string=0x511310 "",  
maxlen=Variable "maxlen" is not available.

) at vsnprintf.c:120
#3  0x2aab4aaf in evbuffer_add_vprintf (buf=0x511160,  
fmt=0x406347 "%s/%d", ap=0x7fff44567b00)

at buffer.c:144
#4  0x2aab4c33 in evbuffer_add_printf (buf=0x511160,  
fmt=0x406347 "%s/%d") at buffer.c:168

#5  0x00402f15 in test_evbuffer () at regress.c:492
#6  0x00403c05 in main (argc=1, argv=0x7fff44567d18) at  
regress.c:905

(gdb)

A couple other complaints:

* CVS seems out of date - it doesn't have evdns.c, and the http tests  
fail. (They work for me in libevent 1.2)
* evhttp.c doesn't compile for me with USE_DEBUG in either current  
CVS or libevent 1.2. Looks like some data structures have changed  
since the event_debug()s were written.


Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>



event-once-leak.patch
Description: Binary data


event-poll-leak.patch
Description: Binary data


event-signal.patch
Description: Binary data
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] libevent 1.2

2006-10-18 Thread Scott Lamb

On Oct 18, 2006, at 11:49 AM, William Ahern wrote:

On Wed, Oct 18, 2006 at 12:04:11AM -0600, Jason Ish wrote:
I ran across at least one criticism of libevent gaining too much  
other

than pure event library:
http://varnish.projects.linpro.no/wiki/EventLibrary



All of these criticisms are partially or wholly invalid.

The DNS and HTTP code is effectively only distributed in the  
tarball; it's

not part of the library itself.


Presumably they _will_ be in the library, but I don't see the  
problem, either. I'm using libevent in a resource-constrained system,  
and typing "p4 delete foo.c" didn't take much of my time. (By the  
way, Niels, if you at some point get a 2wire iNID, look for your name  
in the user manual. :) On a less-constrained system, you can simply  
not use those parts of the library.


I don't understand the issue with struct event_base. Obviously it  
evolved,
but I don't understand how the current API is any less useful to a  
threaded

application.


I agree with this part - I don't like the "default base" concept  
either. My complaint is simple: it's error-prone. If you forget  
event_base_set on an event, it's associated with the latest base  
created. This will probably work *most* of the time. It'd be much  
less confusing if it consistently broke. But I understand libevent  
has to keep backward compatibility in mind, and I still haven't  
decided what I'd actually like in a threaded event library, so I'm  
not proposing any changes, at least right now.


The timestamp issue sounds like, "it doesn't have my particular pet  
feature,
so the library is misdesigned". First of all, why is anybody  
depending on
timestamps in such a pervasive manner as to want it built into the  
libevent

API, knowing or not knowing that the timestamp may or may not be the
particular timestamp the application desires (timestamp on a signal
delivered through a pipe flushed at the end of a loop... how is that
remotely useful for something seriously depending on a timestamp?).  
I *have*
written code to give back a fixed timestamp per loop, and maybe it  
would be

convenient if I could access libevent's copy, but I wouldn't criticize
libevent for that.


I don't know what their complaint is, but I had to modify libevent's  
timer stuff in my copy to achieve two purposes:


1) abrupt clock sets. (Our clock starts at epoch on boot, then gets  
set to a real time via SNTP.) There's code in there to handle this,  
but I didn't understand/trust it, so I removed it in favor of just  
using CLOCK_MONOTONIC. Unfortunately, it's not that portable -  
notably, stupid OS X still doesn't support it. Otherwise I'd send in  
a patch.


2) recurring timers without drift. I made my copy just take absolute  
uptimes, but you could probably achieve most of the same thing by  
implementing EV_PERIODIC for timers.


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] libevent 1.2

2006-10-17 Thread Scott Lamb

On Oct 17, 2006, at 11:08 AM, Rhythmic Fistman wrote:

That's funny, there doesn't seem to be a self-pipe-trick
implementation in lib-evt... how do you get by without it?


There is, although it uses a socketpair() instead of a pipe().

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] libevent 1.2

2006-10-17 Thread Scott Lamb

On Oct 17, 2006, at 12:19 PM, Rhythmic Fistman wrote:

On 10/17/06, Scott Lamb <[EMAIL PROTECTED]> wrote:

On Oct 17, 2006, at 11:08 AM, Rhythmic Fistman wrote:
> That's funny, there doesn't seem to be a self-pipe-trick
> implementation in lib-evt... how do you get by without it?

There is, although it uses a socketpair() instead of a pipe().


Ah, I was grepping "trick". It looks like it's used internally in
the signal style implementations - so how does a multithreaded
app get thread_dispatch to return when it's time to exit?


libevent doesn't have any interthread communication. But you can  
layer stuff on top of it - look through the archives for a couple  
posts by Andrew Danforth.


Message-ID:  
<[EMAIL PROTECTED]>

Date: Thu, 5 Oct 2006 21:42:35 -0400
From: "Andrew Danforth" <[EMAIL PROTECTED]>
References: <[EMAIL PROTECTED]>
Subject: [Libevent-users] Re: Passing data between event loops in
multithreaded apps

and his code at <http://www.weirdness.net/code/libevent>

I've been thinking that a fancier threading system might perform  
better, but I still haven't found the time to write and benchmark  
different approaches.


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Can't get libevent ( event-test.c ) to work on OS X ( 10.4.8 )!

2006-10-09 Thread Scott Lamb

On Oct 9, 2006, at 11:41 AM, Niels Provos wrote:

You should really just use the code in regress.c  event-test.c is very
old.  BTW, the open O_NONBLOCK behavior is different across the
different operating systems.  This code works fine on *BSD systems.


Maybe the broken sample code could be deleted? Or would you like a  
patch to fix it? Or at least a README in the sample directory saying  
that it's old'n'busted?


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[PATCH] Re: [Libevent-users] SIGCHLD handling problems

2006-09-21 Thread Scott Lamb
I was playing with the signal handling code anyway (seemed too  
complicated for me), so I've got a patch that fixes this problem and  
provides a new regress test. It just makes changes immediately in  
evsignal_add() and evsignal_del() and does not block/unblock signals.


This patch does not get rid of ncalls, which I'm also thinking of  
doing, as I mentioned in an earlier message to the list.


devpoll.c  |   15 +++
epoll.c|   15 +++
evport.c   |   17 +++--
evsignal.h |8 ++
poll.c |   15 +++
select.c   |   14 +++---
signal.c   |   74 +++ 
+-

test/regress.c |   32 
8 files changed, 76 insertions(+), 114 deletions(-)

There's one subtlety to it. With my change, evsignal_process() runs  
with signals unblocked, so timing is critical. The original code is  
then racy:


TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
ncalls = evsigcaught[EVENT_SIGNAL(ev)]; <-- point A
if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
}
}

memset(evsigcaught, 0, sizeof(evsigcaught));<-- point B
evsignal_caught = 0;<-- point C

For any signal that is not already pending (ncalls == 0 when reaching  
its point A), if it arrives between then and its ncalls being cleared  
in point B, it will be lost. If it arrives after then but before  
evsignal_caught in point C, it will be arbitrarily delayed (until  
another signal comes along to set 	evsignal_caught).


I solved this by

* moving the evsignal_caught to before checking the individual  
signals for delivery (but after evsignal_caught is checked itself, in  
a different function).
* setting "evsigcaught[x] = 0" only when we are setting that signal  
active.


--
Scott Lamb <http://www.slamb.org/>



event-signal.patch
Description: Binary data
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Multithreaded behavior

2006-09-08 Thread Scott Lamb

On Sep 8, 2006, at 12:13 PM, William Ahern wrote:
Ah. I was approaching it from another angle (one thread per event  
loop, and
the question being how to inject events and balance events into  
each event

loop).


Like the first thing I described? Have you actually done this and had  
any luck with it? I suppose I could give it a go, at least for a  
simple balancing scheme.



I'd never want to touch the above scheme w/ a ten foot pole, mostly
because one of the greatest benefits I enjoy with event-oriented  
programming

is the lack of contention (i.e. not having to use a mutex everywhere).


I don't like the idea of losing that either, but there's no getting  
around having some sort of multiprocessing if you're going to use  
multiple processors, and recent hardware changes are making it harder  
to justify not doing so.




There are lots of scenarios where I might have multiple events  
outstanding,
all related to a single context (TCP proxying, for instance). In  
the above
design, I'd have to begin littering mutexes around my code.  
Relating those
oustanding events to a shared event loop implicitly frees me from  
having to

deal w/ this problem.


Yeah, that's certainly true for my SSL proxy. There'd need to be some  
sort of grouping of events, and I'm not sure how that should work if  
a new member is reported while the event is out for delivery. Held  
until next time, I guess.


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Multithreaded behavior

2006-09-08 Thread Scott Lamb

On Sep 8, 2006, at 10:18 AM, Scott Lamb wrote:

lock
loop:
while there are events:
dequeue one
unlock
handle it
lock
if someThreadPolling:
condition wait
else:
someThreadPolling = true
poll for events
lock


Oops, here's where "someThreadPolling = false" should go.


fire condition
    unlock


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Multithreaded behavior

2006-09-08 Thread Scott Lamb

On Sep 7, 2006, at 11:49 PM, William Ahern wrote:

On Thu, Sep 07, 2006 at 11:29:50PM -0700, Scott Lamb wrote:

I think libevent's current multithreaded behavior is not terribly
useful:

1. You can't safely share a single event_base among a pool of
threads. This is actually what I'd like to do with threads,
especially now that four-core systems are becoming cheap. (My SSL
proxy should be able to put those extra cores to use.)
It's...tricky...to get right, though.


Why would you ever want to do this? I mean, in one sense it could  
simplify
some multi-threaded designs. The complexity it adds, however,  
hardly seems
worth it compared to how simple this could be done on a per- 
application

basis using the existing API.


How would you do it with the existing API? The best I've got is to have:

(1) an "acceptor" thread which just works on the listen sockets and  
throws accepted sockets to other threads based on some heuristic

(2) the "worker" threads that actually handle connections

The acceptor would lock, throw something into the target's "hey, add  
this" queue, then send it a wakeup.


But there are a couple performance aspects that I don't like:

(1) There's really no guarantee the workers are equally busy.
(2) No connection can actually proceed without being transferred  
across threads.


Maybe (1) could be addressed with some sort of rebalancing  
scheme...but at that point, it might get as complicated as the scheme  
below, and each application would have to implement that complexity.


Actually, to get this right from both an aesthetic as well as  
efficiency
perspective would require, I think, libevent to be able to poll on  
both a

condition variable as well as traditional descriptor objects.


At a high level, I think it would require the basic poll algorithm to  
be:


lock
loop:
while there are events:
dequeue one
unlock
handle it
lock
if someThreadPolling:
condition wait
else:
someThreadPolling = true
poll for events
lock
fire condition
unlock

so whatever thread happens to notice that it's out of events does a  
poll, and the others can see the results immediately. But I haven't  
addressed actually putting new fds into the poll array. I'm not sure  
what the behavior there has to be. I admit it - this approach is  
complicated.


Anyway, I'm not suggesting adopting this without actual proof that  
it's better. I need to blow the dust off my benchmark tools, but I'm  
willing to put the effort into trying things out if I hear ideas I like.



Maybe the
underlying capability could feasibly be added to kqueue's  
Nonetheless

it's a pretty far fetched proposition.


Well, I'm definitely not the first person to have suggested handling  
events in multiple threads simultaneously. Take a look at:


* Java's nio API. I don't know if it's horribly complicated inside,  
and I haven't used it in this way, much less actually benchmarked it,  
but they have some discussion of concurrency in their API docs. From  
<http://java.sun.com/j2se/1.5.0/docs/api/index.html>, take a look at  
java.nio.channels.Selector, "Concurrency" section.


* SEDA - http://www.eecs.harvard.edu/~mdw/proj/seda/

* Jeff Darcy's design notes - http://pl.atyp.us/content/tech/ 
servers.html


Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] Multithreaded behavior

2006-09-07 Thread Scott Lamb
I think libevent's current multithreaded behavior is not terribly  
useful:


1. You can't safely share a single event_base among a pool of  
threads. This is actually what I'd like to do with threads,  
especially now that four-core systems are becoming cheap. (My SSL  
proxy should be able to put those extra cores to use.)  
It's...tricky...to get right, though.


2. If you forget event_base_set on an event, it's associated with the  
latest base created. This will probably work most of the time. It'd  
be much less confusing if it consistently broke.


3. Each new base created leaks the existing ev_signal_pair descriptors.

4. Signals are delivered to whatever event loop happens to see them  
first.


5. It uses sigprocmask(), which has undefined behavior when threads  
are in use. [1]


6. You can't destroy an event_base.

I'm not sure what the ideal thread behavior would be, though, much  
less how to achieve it in a backward-compatible way. Opinions?


[1] http://www.opengroup.org/onlinepubs/007908799/xsh/sigprocmask.html

--
Scott Lamb <http://www.slamb.org/>

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] Signal handling - ncalls

2006-09-07 Thread Scott Lamb

I don't understand the purpose of "ncalls" in the evsignal code:

* For normal signals, the kernel simply keeps a bitmask of  
undelivered signals. So ncalls is lossy - if the signal isn't  
delivered by the kernel before another one arrives, one is "lost".  
Since signals are currently blocked basically any time not in poll(),  
this is extremely likely if the process is busy. In practice, I  
generally see normal signals used in places where this bitmask is  
appropriate - "reread your configuration file and check for log  
rotation", "terminate", etc. It's not important how many of these  
events were received; only that a signal is delivered some time after  
the latest one.


* Realtime signals are actually queued, but they come with a bunch  
more information (siginfo_t) which libevent discards. I'm not sure  
what purpose individual delivery would serve without this extra per- 
delivery structure.


Is anyone using this feature? I'm tempted to remove it. If there's  
interest, I'd be happy to write a patch that does the following:


(1) removes all the "ncalls" stuff
(2) removes the signal blocking/unblocking stuff (signal_(recalc| 
deliver)) and makes signal_(add|del)() do their own work.
(3) reorders evsignal_process() slightly to make it correct when  
running with unblocked signals. (I'll also describe this in more  
detail.)


The goal being simplicity, and a maybe a touch more speed. (The  
signal blocking/unblocking means unnecessary system calls.)


--
Scott Lamb <http://www.slamb.org/>

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] [PATCH] once memory leak

2006-09-07 Thread Scott Lamb
In event_once, if event_add fails, the once structure will be leaked.  
Patch attached.


--
Scott Lamb <http://www.slamb.org/>



event-once-leak.patch
Description: Binary data
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] poll memory leaks

2006-09-07 Thread Scott Lamb

On Sep 7, 2006, at 11:53 AM, Scott Lamb wrote:

+   int tmp_event_count;
+
if (pop->event_count < 32)
-   pop->event_count = 32;
+   tmp_event_count = 32;
else
-   pop->event_count *= 2;
+   tmp_event_count *= 2;


Err, this last line should be "tmp_event_count = pop->event_count * 2".

--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] [PATCH] poll memory leaks

2006-09-07 Thread Scott Lamb

On Sep 7, 2006, at 11:53 AM, Scott Lamb wrote:
By the way, what's the rationale for the separate event_[rw]_back  
structures and for the idxplus1_by_fd? It seems like the former  
could be combined into a single event_back and the latter replaced  
with a new member of struct event for arbitrary use by the  
event_op. I ask because I'm porting libevent to a platform that  
needs a proprietary extra POLLxxx event type, and it seems  
preferable to remove two of four dynamically-allocated parallel  
arrays instead of adding a fifth.


I should add: this would mean a slight behavior change that if there  
are then two separate struct events for the same file descriptor,  
poll.c would pass them both to poll(). I don't think that's a  
problem, is it?


--
Scott Lamb <http://www.slamb.org/>


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] [PATCH] poll memory leaks

2006-09-07 Thread Scott Lamb
poll_add() in libevent 1.1b and current CVS (revision 1.2) leaks  
memory on realloc() failure. I've attached an untested patch to  
instead preserve the existing contents of the array while still  
returning error. All other libevent uses of realloc() look fine to me.


By the way, what's the rationale for the separate event_[rw]_back  
structures and for the idxplus1_by_fd? It seems like the former could  
be combined into a single event_back and the latter replaced with a  
new member of struct event for arbitrary use by the event_op. I ask  
because I'm porting libevent to a platform that needs a proprietary  
extra POLLxxx event type, and it seems preferable to remove two of  
four dynamically-allocated parallel arrays instead of adding a fifth.


Best regards,
Scott

--
Scott Lamb <http://www.slamb.org/>



event-poll-leak.patch
Description: Binary data


___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users