]> granicus.if.org Git - libevent/commitdiff
be_openssl: don't call do_write() directly from outbuf_cb
authorAzat Khuzhin <a3at.mail@gmail.com>
Fri, 13 Nov 2015 13:00:39 +0000 (16:00 +0300)
committerAzat Khuzhin <a3at.mail@gmail.com>
Wed, 18 Nov 2015 12:40:28 +0000 (15:40 +0300)
Otherwise we can trigger incorrect callback, the simplest way to trigger this
is using http regression tests -- https_chunk_out, since all it do is:
  evhttp_send_reply_end()
    evbuffer_add()
      do_write()
    evhttp_write_buffer()
      evcon->cb = cb

And indeed this is what happens:
  (gdb) bt
  #0  do_write (bev_ssl=0x738a90, atmost=16384) at bufferevent_openssl.c:717
  #1  0x00000000004b69f7 in consider_writing (bev_ssl=0x738a90) at bufferevent_openssl.c:875
  #2  0x00000000004b7386 in be_openssl_outbuf_cb (buf=0x7387b0, cbinfo=0x7fffffffd590, arg=0x738a90) at bufferevent_openssl.c:1147
  #3  0x0000000000490100 in evbuffer_run_callbacks (buffer=0x7387b0, running_deferred=0) at buffer.c:508
  #4  0x00000000004901e5 in evbuffer_invoke_callbacks_ (buffer=0x7387b0) at buffer.c:529
  #5  0x0000000000493a30 in evbuffer_add (buf=0x7387b0, data_in=0x4ecfb2, datlen=5) at buffer.c:1803
  #6  0x00000000004be2e3 in evhttp_send_reply_end (req=0x7371a0) at http.c:2794
  #7  0x000000000045c407 in http_chunked_trickle_cb (fd=-1, events=1, arg=0x75aaf0) at regress_http.c:402
  ...
  (gdb) p bev.writecb
  $4 = (bufferevent_data_cb) 0x4ba17e <evhttp_write_cb>
  $5 = (void *) 0x7379b0
  (gdb) p (struct evhttp_connection *)bev.cbarg
  $6 = (struct evhttp_connection *) 0x7379b0
  (gdb) p $6->cb
  $7 = (void (*)(struct evhttp_connection *, void *)) 0x0

And be_sock don't do like this anyway.

Fixes: https_chunk_out
bufferevent_openssl.c

index 7e4d1744dca046dbc8bfee33b32460428bc1a2ef..37478b6a830d2c8a12d59b3e970ebe22f4be69df 100644 (file)
@@ -1139,14 +1139,13 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
        int r = 0;
        /* XXX need to hold a reference here. */
 
-       if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
-               if (cbinfo->orig_size == 0)
-                       r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
-                           &bev_ssl->bev.bev.timeout_write);
-               consider_writing(bev_ssl);
+       if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN &&
+           cbinfo->orig_size == 0) {
+               r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
+                   &bev_ssl->bev.bev.timeout_write);
        }
        /* XXX Handle r < 0 */
-        (void)r;
+       (void)r;
 }