Menu

#339 openssl + bufferevent + evhttp problem (2.0 and 2.1)

For_2.0
open
nobody
5
2014-09-18
2014-09-18
Alexander
No

openssl + bufferevent + evhttp problem (2.0 and 2.1)

Hello,

I have some problem, when I used openssl + bufferevent in https client.

I used libevent 2.0, but the same problem was found with 2.1, too. (I've checked it with libevent-2.1.4-alpha)

I got evhttp_connection_base_bufferevent_new function from 2.1 to 2.0 (we can't fully use 2.1 for some reasons, but for tests I've check libevent-2.1.4-alpha fully), and did the following steps:

1) Init and create ssl_ctx and ssl object

2) Create bufferevent with ssl
bev = bufferevent_openssl_socket_new (base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);

3) Made bufferevent_openssl_set_allow_dirty_shutdown (bev, 1); // (function from libevent 2.1)

4) create evhttp_connection (with function from libevent 2.1)
evhttp_connection = evhttp_connection_base_bufferevent_new (base, NULL, bev, address, port);

5) set timeout to evhttp_connection with evhttp_connection_set_timeout_tv()

6) using evhttp_connection object for sending https requests.

In general, this schema works fine, but I faced an exceptional situation when https client generates warnings and asserts leading to a core dump.

1) Create a connection to valid host name, but to closed port and send request.

2) As I understand ssl is tries to make handshake, but handshake is timeouted (because the port is closed) and request will fail.

3) After that, timeout will expire again!!! and, handshake callback calls again (this is a persistent callback)!
event_assign(&bev->ev_read, bev->ev_base, fd, EV_READ|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);
event_assign(&bev->ev_write, bev->ev_base, fd, EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);

4) Libevent generates the following warnings (as I understand fd does not exist, because request (handshake) failed after the first timeout):
Epoll MOD(4) on fd 14 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor
Epoll MOD(1) on fd 14 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor

5) After that generate core dump:
http.c:711: Assertion req != NULL failed in evhttp_connection_fail

Backtrace:
#0 0xb7714424 in __kernel_vsyscall ()
#1 0xb742ee0f in __GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 0xb7432455 in __GI_abort () at abort.c:91
#3 0x08245e2a in libeventFatalCallback ()
#4 0x08782a44 in event_exit (errcode=-559030611) at log.c:76
#5 0x08782b83 in event_errx (eval=-559030611, fmt=0x9b187cc "%s:%d: Assertion %s failed in %s") at log.c:136
#6 0x0878ec52 in evhttp_connection_fail (evcon=0xa626270, error=EVCON_HTTP_TIMEOUT) at http.c:711
#7 0x0878ee98 in evhttp_error_cb (bufev=0xa5e8280, what=64, arg=0xa626270) at http.c:1413
#8 0x0878ef6c in evhttp_connection_cb (bufev=0xa5e8280, what=64, arg=0xa626270) at http.c:1440
#9 0x0877b994 in bufferevent_run_deferred_callbacks_locked (_=0xa5e8368, arg=0xa5e8280) at bufferevent.c:160
#10 0x0876bd15 in event_process_deferred_callbacks (queue=0xa5a372c, breakptr=0xa5a3708) at event.c:1387
#11 0x0876f79f in event_process_active (base=<optimized out="">) at event.c:1428
#12 event_base_loop (base=0xa5a3680, flags=1) at event.c:1617

evhttp_error_cb calls with follow flags (what) and states:
first time:
state: 1 (EVCON_CONNECTING)
what: 0x40 (BEV_EVENT_TIMEOUT)

second time:
state: 3 (EVCON_READING_FIRSTLINE)
what: 0x11 (BEV_EVENT_EOF | BEV_EVENT_READING)

Before third times generated warning messages (described above)

third times:
state: 0 (EVCON_DISCONNECTED)
what: 0x40 (BEV_EVENT_TIMEOUT)

After that generated core dump.

I've tried to play with flags for bufferevent_openssl_socket_new, and with "dirty_shutdown" - it wasn’t much of a success.
If I make handshake callback as non persistent in libevent code (after that warning will not be generated), and remove evhttp_connection after failing request in our code (after that timer won’t expire, and core dumps won’t be generated), the problem will be solved. But I'm not sure that is correct.

For a simple http client, this issue does not reproduce itself, and evhttp_error_cb calls only twice (first and second)

Help me, please!!!!!

Discussion


Log in to post a comment.