There are two possible ways of getting response from the server:
- processing existing bufferevent buffer
- reading from the socket (even after write() errored with -1, it is
still possible)
But we did not tried the first option, only the second one.
Fixes: http/read_on_write_error (on freebsd/osx)
In 755fbf16c ("Add void* arguments to request_new and reply_new
evrpc hooks") this new functions had been introduced, but newer used,
what for? So let's use them.
We should not attemp to establishe the connection if there is retry
timer active, since otherwise there will be a bug.
Imagine next situation:
con = evhttp_connection_base_new()
evhttp_connection_set_retries(con, 2)
req = evhttp_request_new()
evhttp_make_request(con, req, ...)
# failed during connecting, and timer for 2 second scheduler (retry_ev)
Then another request scheduled for this evcon:
evhttp_make_request(con, req, ...)
# got request from server,
# and now it tries to read the response from the server
# (req.kind == EVHTTP_RESPONSE)
#
# but at this point retry_ev scheduled,
# and it schedules the connect again,
# and after the connect will succeeed, it will pick request with
# EVHTTP_RESPONSE for sending and this is completelly wrong and will
# fail in evhttp_make_header_response() since there is no
# "http_server" for this evcon
This was a long standing issue, that I came across few years ago
firstly, bad only now I had time to dig into it (but right now it was
pretty simple, by limiting amount of CPU for the process and using rr
for debug to go back and forth).
MSVC does not support SHARED and STATIC libraries with the same name,
so let's just build SHARED libraries by default instead (yes we can add
prefix but let's stick with this).
The reason for this is that in windows shared libraries requires .lib
file too, but this is not static library it is imported library for
shared (doh...), for more info [1] and [2].
[1]: https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-creation
[2]: https://blogs.msdn.microsoft.com/oldnewthing/20091013-00/?p=16403
And when we build both static library can and will override shared
library imported part, let's take a look at event_extra.lib:
- before patch [3]:
$ less libevent-fail/lib/Debug/event_extra.lib | head
==> use library:contained_file to view a file in the archive
rw-rw-rw- 100666/100666 59568 Nov 21 23:55 2018 event_extra_static.dir/Debug/evrpc.obj
rw-rw-rw- 100666/100666 252219 Nov 21 23:55 2018 event_extra_static.dir/Debug/evdns.obj
rw-rw-rw- 100666/100666 203850 Nov 21 23:55 2018 event_extra_static.dir/Debug/http.obj
rw-rw-rw- 100666/100666 25907 Nov 21 23:55 2018 event_extra_static.dir/Debug/event_tagging.obj
[3]: https://ci.appveyor.com/project/azat/libevent/builds/20472024/job/t0o93v042jai0dj7
- "after patch" [4] (not after but the same effect):
$ less libevent-ok/lib/Debug/event_extra.lib | head
==> use library:contained_file to view a file in the archive
--------- 0/0 509 Nov 21 23:38 2018 event_extra.dll
...
[4]: https://ci.appveyor.com/project/azat/libevent/builds/20478998/job/ca9k3c76amc4qr76
Refs: #691
Long time ago in [1] cmake build was forced to compile both libraries
(SHARED and STATIC), since this is how our autotools build works.
[1]: 7182c2f561570cd9ceb704623ebe9ae3608c7b43 ("cmake: build SHARED and STATIC libraries (like autoconf does)")
And there is no way to configure this (and indeed you need to do this
for MSVC for example), so let's introduce option for this --
EVENT__LIBRARY_TYPE.
Plus now we have INTERFACE libraries, that we can use internally in
libevent's cmake rules to avoid strict to _shared/_static variant of the
libraries to link with samples/tests (we prefer SHARED over STATIC for
linking).
Also bump minimal cmake required version to 3.1 by the following
reasons:
- 3.1 is required for RPATH configuration under APPLE
- 3.0 is required for add_library(INTERFACE) (did not found it in 2.8.x
documentation)
- remove extra conditions
(anyway 3.1 was release 4 years ago, so I guess that most of the systems
will have it)
This patch mark testcases that only fail under travis-ci/appveyor with
TT_RETRIABLE, since otherwise there is too much noise, other issues
(like failures under vagrant boxes) would be investigated separatelly.
linux (from travis-ci only):
- http/cancel_by_host_no_ns
- http/cancel_by_host_inactive_server
- http/cancel_by_host_ns_timeout
- http/cancel_by_host_ns_timeout_inactive_server
- thread/conditions_simple
- util/monotonic_prc_precise
- util/usleep
- main/del_wait
vagrant/ubuntu box (this is the only exception):
- thread/no_events
win32 (from appveyor only):
- main/active_later
- main/persistent_active_timeout
And we should use TT_RETRIABLE over TT_OFF_BY_DEFAULT/TT_SKIP when it
make sense.
But there is still "test-ratelim__group_lim" left.
We have some tests that has false-positive due to real/CPU time bound,
but they are pretty generic and we do not want to skip them by default.
TT_RETRIABLE is the flag that will indicate tinytest to retry the test
in case of failure, use it to avoid next possible false-positives:
- real time-related
- CPU time-related
Since I guess it is better to see/grepping RETRYING messages over
ignoring completely failed builds.
No configuration switch for number of retries was done on purpose (only
3 retries and no more).
And this is how it looks BTW:
$ gcc ../test/tinytest_demo.c ../test/tinytest.c
$ ./a.out --verbose --no-fork
demo/timeout_retry
demo/timeout_retry:
FAIL ../test/tinytest_demo.c:201: assert(i != 1): 1 vs 1
[timeout_retry FAILED]
[RETRYING timeout_retry (3)]
demo/timeout_retry:
OK ../test/tinytest_demo.c:201: assert(i != 1): 2 vs 1
OK ../test/tinytest_demo.c:213: assert(t2-t1 >= 4): 5 vs 4
OK ../test/tinytest_demo.c:215: assert(t2-t1 <= 6): 5 vs 6
1 tests ok. (0 skipped)
We have calls to the next functions but do not check return values,
though they can be invalid and it is better to show this somehow.
Also do bufferevent_setfd() first and only after it
bufferevent_enable()/bufferevent_disable() since:
a) it is more natural
b) it will avoid extra operations
c) it will not fail first bufferevent_enable() (this is the case for
buffbufferevent_async at least)
In this case we could add more information for issues like #709
* iocp-fixes:
regress: test for HTTP/HTTPS with IOCP enabled
bev_async: trigger/run only deferred callbacks
bev_async: do not initialize timeouts multiple times
bev_async: set "ok" on setfd if fd>=0 (like we do during creation)
bev_async: ignore ERROR_INVALID_PARAMETER on .setfd for iocp
Closes: #709
Refs: nmathewson/Libevent#160
Otherwise callbacks will be runned even without event_loop, due to
nature of IOCP.
A simple example is:
evhttp_connection_free(client)
# freeing the client will trigger evhttp_connection_free() for the
# client on the server side, and hence there will double free
evhttp_free(server)
Fixes: iocp/http/simple
You cannot event_assign() event multiple times, this is UB, and most
likely will fail.
Fixes: af9b2a7ae0be11c79a909d212b1833a9379e4ba0 ("Initialize async
bufferevent timeout CBs unconditionally")
listener already calls event_iocp_port_associate_() the second call will
return ERROR_INVALID_PARAMETER.
Plus we already ignore it on creation, so why we should care about it
here?
Although this is not a problem, since bufferevent uses finalizers and
will free itself only from the loop (well this is not a problem if you
do not play games with various event_base in different threads) it
generates questions, so rewrite it in more reliable way.
Fixes: #712
Some improvements for http-server sample:
- getopt
- persistent port via -p option
- IOCP for win32 via -I
- disable buffering
- enable debug logging via -v/EVENT_DEBUG_LOGGING_ALL
- cleanup (by signal and separate error path on errors)
* sample-http-server:
s/http-server: graceful cleanup
s/http-server: enable debug logging if EVENT_DEBUG_LOGGING_ALL env isset
s/http-server: turn off buffering (otherwise do output on win32)
s/http-server: add an option to use IOCP
s/http-server: add options (for persistent port)
Refs: #709
Since:
- it is not a library
- this file should have (if I had enough time) enough fixes in itself
and should not polute libevent history
- it "requires" (it more cleaner to use it in this way) script --
tools/vagrant-tests.py (indeed, from libevent-extras)
- will has it's own issues/README/...
https://github.com/libevent/libevent-extras