[Libevent-users] SIGPIPE in multithreaded program

2008-01-21 Thread Ron Arts

Hi,

I am using libevent in a multithreaded program, the main
thread containing the libevent loop, and other threads
doing disk I/O. From mail from this list, and the changelogs
I was under the impression that libevent handles signals
better in a multithreaded environment since 1.3, but now
I think I was wrong.

Is it necessary to specifically ignore signals in every
thread I create?

Thanks,
Ron




smime.p7s
Description: S/MIME Cryptographic Signature
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


[Libevent-users] SSL enabling libevent programs, is there an example available?

2008-01-21 Thread Ron Arts

Hi,

subject says it all. If there's no example with
libevent, can someone recommend another place to look?
I tried Googling but couldn't find a concise example.

Thanks,
Ron


smime.p7s
Description: S/MIME Cryptographic Signature
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


[Libevent-users] thread-safety (and performance)

2008-01-21 Thread Tani Hosokawa
When initiating HTTP requests in a multi-threaded process, under any 
significant load you will start finding horrible memory corruption 
problems, sometimes resulting in bad requests and sometimes resulting in 
core dumps.  Also, under any significant load, you'll probably find that 
you are dropping a large number of connections due to the listen queue 
overflowing while your code is performing some other task.  This is a 
patch that I think largely deals with these.  Also, http_hostportfile() 
is not thread-safe, so I've attached a thread-safe version that can be 
used in its place (unfortunately I can't think of any clean way to make 
the current interface thread-safe without introducing a memory leak).


/* TH: remember to free() opaque after you're done with this */
int
http_hostportfile_r(const char *url, char **phost, u_short *pport, char 
**pfile,void **opaque)

{
   struct http_hostportfile_threadsafe_opaque {
  char shost[1024];
  char sfile[1024];
   } *opaquedata;
   opaquedata = malloc(sizeof(*opaquedata));
   *opaque = opaquedata;
   char *p, *p2;
   int len;
   u_short port;

   len = strlen(HTTP_PREFIX);
   if (strncasecmp(url, HTTP_PREFIX, len))
   return (-1);

   url += len;

   /* We might overrun */
   if (strlcpy(opaquedata-shost, url, sizeof(opaquedata-shost)) 
= sizeof(opaquedata-shost))

   return (-1);

   p = strchr(opaquedata-shost, '/');
   if (p != NULL) {
   *p = '\0';
   p2 = p + 1;
   } else
   p2 = NULL;

   if (pfile != NULL) {
   /* Generate request file */
   if (p2 == NULL)
   p2 = ;
   snprintf(opaquedata-sfile, sizeof(opaquedata-sfile), 
/%s, p2);

   }

   p = strchr(opaquedata-shost, ':');
   if (p != NULL) {
   *p = '\0';
   port = atoi(p + 1);

   if (port == 0)
   return (-1);
   } else
   port = HTTP_DEFAULTPORT;

   if (phost != NULL)
   *phost = opaquedata-shost;
   if (pport != NULL)
   *pport = port;
   if (pfile != NULL)
   *pfile = opaquedata-sfile;

   return (0);
}


Index: http.c
===
--- http.c  (revision 1)
+++ http.c  (working copy)
@@ -308,7 +308,7 @@
evhttp_make_header_request(struct evhttp_connection *evcon,
struct evhttp_request *req)
{
-   static char line[1024];
+   char line[1024];
   const char *method;

   evhttp_remove_header(req-output_headers, Accept-Encoding);
@@ -378,9 +378,9 @@
evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
long content_length)
{
+   char len[12]; /* XXX: not thread-safe */
   if (evhttp_find_header(headers, Transfer-Encoding) == NULL 
   evhttp_find_header(headers, Content-Length) == NULL) {
-   static char len[12]; /* XXX: not thread-safe */
   snprintf(len, sizeof(len), %ld, content_length);
   evhttp_add_header(headers, Content-Length, len);
   }
@@ -394,7 +394,7 @@
evhttp_make_header_response(struct evhttp_connection *evcon,
struct evhttp_request *req)
{
-   static char line[1024];
+   char line[1024];
   snprintf(line, sizeof(line), HTTP/%d.%d %d %s\r\n,
   req-major, req-minor, req-response_code,
   req-response_code_line);
@@ -433,7 +433,7 @@
void
evhttp_make_header(struct evhttp_connection *evcon, struct 
evhttp_request *req)

{
-   static char line[1024];
+   char line[1024];
   struct evkeyval *header;

   /*
@@ -1999,7 +1999,7 @@
   if ((fd = bind_socket(address, port)) == -1)
   return (-1);

-   if (listen(fd, 10) == -1) {
+   if (listen(fd, 8192) == -1) {
   event_warn(%s: listen, __func__);
   EVUTIL_CLOSESOCKET(fd);
   return (-1);

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


Re: [Libevent-users] thread-safety (and performance)

2008-01-21 Thread William Ahern
On Mon, Jan 21, 2008 at 04:14:08PM -0800, Tani Hosokawa wrote:
snip
 @@ -1999,7 +1999,7 @@
if ((fd = bind_socket(address, port)) == -1)
return (-1);
 
 -   if (listen(fd, 10) == -1) {
 +   if (listen(fd, 8192) == -1) {
event_warn(%s: listen, __func__);
EVUTIL_CLOSESOCKET(fd);
return (-1);

Probably better to use SOMAXCONN instead of an arbitrary number.

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


Re: [Libevent-users] SSL enabling libevent programs, is there an example available?

2008-01-21 Thread Thomas Harning

Ron Arts wrote:

Hi,

subject says it all. If there's no example with
libevent, can someone recommend another place to look?
I tried Googling but couldn't find a concise example. 
For example, w/ OpenSSL you can turn the socket to be non-blocking and 
watch for what openssl 'needs' after a failed attempt to read/write...

Ex:
int ret = SSL_read(ssl, buffer, len);
if(ret  0) {
   int err = SSL_get_error(ret);
   switch(err) {
case SSL_ERROR_WANT_WRITE:
   /* Hook up libevent to wait on write then retry w/ exact same 
argument */

   break;
   case SSL_ERROR_WANT_READ:
  /* Hook up libevent to wait on read then ... */
  break;
   default: /* Something else. */
 }
}
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] SSL enabling libevent programs, is there an example available?

2008-01-21 Thread William Ahern
On Tue, Jan 22, 2008 at 01:09:11AM +0100, Ron Arts wrote:
 Hi,
 
 subject says it all. If there's no example with
 libevent, can someone recommend another place to look?
 I tried Googling but couldn't find a concise example.
 

http://25thandclement.com/~william/projects/libevnet.html

Download the tarball. OpenSSL bindings are in src/tls.c. There's lots more
code in the library for integrating with libevent, but I wrote tls.c many
years ago (before libevnet, and possibly before libevent), and it should be
easy to rip it out and use however you want.

At the very least, tls_read_try(), tls_write_try() and tls_accept_try()
should help you out.

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


Re: [Libevent-users] SIGPIPE in multithreaded program

2008-01-21 Thread Ron Arts

William Ahern wrote:

On Tue, Jan 22, 2008 at 01:06:30AM +0100, Ron Arts wrote:

Hi,

I am using libevent in a multithreaded program, the main
thread containing the libevent loop, and other threads
doing disk I/O. From mail from this list, and the changelogs
I was under the impression that libevent handles signals
better in a multithreaded environment since 1.3, but now
I think I was wrong.

Is it necessary to specifically ignore signals in every
thread I create?


In Unix it's necessary to change the default behavior of SIGPIPE if you
don't want your process killed. libevent, AFAIK, won't do this for you. If
won't independently setup handlers for all the different signals. Most
daemon applications ignore SIGPIPE as part of their initialization. The
default behavior caters to simple shell applications that can't be bothered
to check the return value of a write.

#include signal.h

struct sigaction sa;

sa  = sa_initializer;
sa.sa_handler   = SIG_IGN;
sa.sa_flags = 0;

sigemptyset(sa.sa_mask);

if (0 != sigaction(SIGPIPE, sa, 0))
err(EXIT_FAILURE, sigaction);


Oops, I'm sorry, I did not make myself clear, while writing the
email I edited it a lot, and forgot to mention that indeed I
ignore SIGPIPE in my initialisation code:

  struct event evsigpipe;

  event_init();
  event_set(evsigpipe, SIGPIPE, EV_SIGNAL|EV_PERSIST, signal_cb, evsigpipe);
  event_add(evsigpipe, NULL);
  event_dispatch();

void signal_cb(int fd, short event, void *arg)
{
  struct event *signal = arg;
extern int reload_database;

  switch(EVENT_SIGNAL(signal)) {
case SIGTERM: // sigterm
fprintf(stderr, Killed);
exit(1); break;
case SIGHUP:  // sighup
fprintf(stderr, Got SIGHUP);
reload_config = TRUE;
break;
case SIGUSR1:  // reload entire database
fprintf(stderr, Got SIGUSR1);
reload_database = TRUE;
break;
default:
fprintf(stderr, %s: got signal %d, __func__, EVENT_SIGNAL(signal));
break;
  }
}

But my program is still being killed with SIGPIPE occasionally.
I am using threads, and I presume sometimes one of the other threads
receives the SIGPIPE signal instead of the main thread, and I
*think* that in such a case my program exits.

But what I meant to ask was: isn't libevent supposed (since 1.3) to handle
multithreading and ensure that only one thread receives the signal?
Or should I specifically add code at the beginning of each thread
to ignore SIGPIPE?

Thanks,
Ron


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




smime.p7s
Description: S/MIME Cryptographic Signature
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users