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

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



The following code is a modified version of the example http client at
http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html#_launching_connections_by_hostname

It just seems to exit. The only difference is that I create the socket manually

int fd = socket(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(fd);

I need to create the socket manually in order to bind the outgoing IP
( see http://archives.seul.org/libevent/users/Dec-2009/msg00025.html
).

If I run it without a debugger, it just exits (says "Closing"). If I
run it with gdb, I get the output at the bottom of this message.

/* Don't actually copy this code: it is a poor way to implement an
   HTTP client.  Have a look at evhttp instead.
*/
#include <event2/dns.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/event.h>

#include <stdio.h>

void readcb(struct bufferevent *bev, void *ptr)
{
    char buf[1024];
    int n;
    struct evbuffer *input = bufferevent_get_input(bev);
    while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0) {
        fwrite(buf, 1, n, stdout);
    }
}

void eventcb(struct bufferevent *bev, short events, void *ptr)
{
    if (events & BEV_EVENT_CONNECTED) {
         printf("Connect okay.\n");
    } else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
         struct event_base *base = (event_base *)ptr;
         printf("Closing\n");
         bufferevent_free(bev);
         event_base_loopexit(base, NULL);
    }
}

int main(int argc, char **argv)
{
    struct event_base *base;
    struct evdns_base *dns_base;
    struct bufferevent *bev;

    if (argc != 3) {
        printf("Trivial HTTP 0.x client\n"
               "Syntax: %s [hostname] [resource]\n"
               "Example: %s www.google.com /\n",argv[0],argv[0]);
        return 1;
    }

    base = event_base_new();
    dns_base = evdns_base_new(base, 1);

	int fd = socket(AF_INET, SOCK_STREAM, 0);
	evutil_make_socket_nonblocking(fd);

	printf("fd=%d\n", fd);

    bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, readcb, NULL, eventcb, base);
    bufferevent_enable(bev, EV_READ|EV_WRITE);
    evbuffer_add_printf(bufferevent_get_output(bev), "GET %s\r\n", argv[2]);
    bufferevent_socket_connect_hostname(
        bev, dns_base, AF_UNSPEC, argv[1], 80);
    event_base_dispatch(base);
    return 0;
}


gdb:


$ gdb -ex run --args ./evex www.google.com /
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/mihai/frogmod/evex...done.
Starting program: /home/mihai/frogmod/evex www.google.com /
[Thread debugging using libthread_db enabled]
fd=10
Closing

Program received signal SIGPIPE, Broken pipe.
0x0030f422 in __kernel_vsyscall ()
(gdb) bt
#0  0x0030f422 in __kernel_vsyscall ()
#1  0x00b67b61 in __libc_writev (fd=12468212, vector=0xbfffee60,
count=1) at ../sysdeps/unix/sysv/linux/writev.c:51
#2  0x08050740 in evbuffer_write_iovec (buffer=<value optimized out>,
fd=1, howmuch=-1073746336) at buffer.c:1803
#3  0x08052514 in evbuffer_write_atmost (buffer=0x80669d8, fd=10,
howmuch=7) at buffer.c:1881
#4  0x08052600 in evbuffer_write (buffer=0x80669d8, fd=10) at buffer.c:1904
#5  0x080542f0 in bufferevent_writecb (fd=10, event=4, arg=0x80668d0)
at bufferevent_sock.c:236
#6  0x0804c4fa in event_process_active_single_queue (base=0x8066020,
flags=<value optimized out>) at event.c:931
#7  event_process_active (base=0x8066020, flags=<value optimized out>)
at event.c:984
#8  event_base_loop (base=0x8066020, flags=<value optimized out>) at
event.c:1167
#9  0x0804cfc9 in event_base_dispatch (event_base=0x8066020) at event.c:1011
#10 0x08049903 in main ()
(gdb)


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.

Is this a bug or is this my code problem? I don't think libevent
should just exit unexpectedly, so it looks like a bug. If so, i'll
post it on the bug tracker.

The whole purpose was to bind the outgoing IP address.

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