[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] strange exit with hand-made socket and bufferevent



On Tue, Feb 16, 2010 at 12:11 AM, Mihai Draghicioiu
<mihai.draghicioiu@xxxxxxxxx> wrote:

> As you can see, it stops with a SIGPIPE, and i suspect it has
> something to do with the fact that at #2 evbuffer_write_iovec, the fd
> parameter is 1 and at #3 evbuffer_write_atmost the fd parameter is 10.
> The fd created by my socket() call is 10 here.

The fact that the program stops with SIGPIPE isn't actually
a libevent issue.  That's just standard Unix behavior: a write
to a socket that isn't able to handle the write will raise SIGPIPE,
and the default behavior of SIGPIPE is to exit the process.

I've developed a habit of setting up the signal handling
to ignore SIGPIPE in any program that uses sockets,
using code like this:

    #include <signal.h>
    static void setup_signals()
    {
        struct sigaction sa;
        sa.sa_handler = SIG_IGN;
        sa.sa_flags = 0;
        sigemptyset(&(sa.sa_mask));
        sigaction(SIGPIPE, &sa, 0);
    }

Annoying default signal-handling behavior aside, though,
there's still the question of why your program ends up
trying to do a write on an invalid socket in the first place.
The most common cause of SIGPIPE is that the remote
host has closed its end of the connection, but that's not
what's happening in this case.  I believe the reason you
get SIGPIPE is that the write(2) ends up happening
before the socket gets connected.  The order of operations
in your code is basically:

1. Push some data into the bufferevent and enable EV_WRITE
2. Request an asynchronous connection to the remote host:port
3. Start up the event loop
4. Some time later, process the event callback when
   the async connect completes

I think what's happening is that, once the libevent main
loop starts in step 3, it sees that you've requested a write
on the bufferevent and, because EV_WRITE is enabled,
it attempts to write to the socket before the connection
is established -- and possibly before the nonblocking
connect(2) syscall is even invoked.

If that's the root of the problem, the solution is to not
enable EV_WRITE on the bufferevent until you get the
callback indicating that the socket is connected.  I.e.,
do the operations listed above in the order 2, 3, 4, 1
instead of 1, 2, 3, 4.

-Brian
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.