Acer Yang [Sat, 20 Sep 2014 07:25:53 +0000 (15:25 +0800)]
Fix cmake error when the Module path has more than one entry.
CMAKE_MODULE_PATH is usually a list instead of single entry. Especially
for projects contain sub cmake projects. My patch replace the
CMAKE_MODULE_PATH with fixed path, to locate the `.in` file.
Azat Khuzhin [Wed, 12 Nov 2014 17:16:18 +0000 (20:16 +0300)]
evdns: avoid read-after-free in evdns_request_timeout_callback()
In evdns_request_timeout_callback() in case we a giving up, we call
request_finished() which will free() req structure, however we ns from
it to fail it, so save pointer to ns to call nameserver_failed() on
them.
Founded with valgrind:
$ valgrind regress dns/retry
==10497== Memcheck, a memory error detector
==10497== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==10497== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==10497== Command: regress dns/retry
==10497==
dns/retry: [forking] ==10498== Invalid read of size 8
==10498== at 0x4C309D: evdns_request_timeout_callback (evdns.c:2179)
==10498== by 0x49EA95: event_process_active_single_queue (event.c:1576)
==10498== by 0x49EFDD: event_process_active (event.c:1668)
==10498== by 0x49F6DD: event_base_loop (event.c:1891)
==10498== by 0x49F063: event_base_dispatch (event.c:1702)
==10498== by 0x44C7F1: dns_retry_test_impl (regress_dns.c:724)
==10498== by 0x44CF60: dns_retry_test (regress_dns.c:749)
==10498== by 0x48A8A1: testcase_run_bare_ (tinytest.c:105)
==10498== by 0x48A94E: testcase_run_forked_ (tinytest.c:189)
==10498== by 0x48AB73: testcase_run_one (tinytest.c:247)
==10498== by 0x48B4C2: tinytest_main (tinytest.c:434)
==10498== by 0x477FC7: main (regress_main.c:459)
==10498== Address 0x6176ef8 is 40 bytes inside a block of size 342 free'd
==10498== at 0x4C29E90: free (vg_replace_malloc.c:473)
==10498== by 0x4A4411: event_mm_free_ (event.c:3443)
==10498== by 0x4BE8C5: request_finished (evdns.c:702)
==10498== by 0x4C3098: evdns_request_timeout_callback (evdns.c:2178)
==10498== by 0x49EA95: event_process_active_single_queue (event.c:1576)
==10498== by 0x49EFDD: event_process_active (event.c:1668)
==10498== by 0x49F6DD: event_base_loop (event.c:1891)
==10498== by 0x49F063: event_base_dispatch (event.c:1702)
==10498== by 0x44C7F1: dns_retry_test_impl (regress_dns.c:724)
==10498== by 0x44CF60: dns_retry_test (regress_dns.c:749)
==10498== by 0x48A8A1: testcase_run_bare_ (tinytest.c:105)
==10498== by 0x48A94E: testcase_run_forked_ (tinytest.c:189)
==10498==
==10498==
==10498== HEAP SUMMARY:
==10498== in use at exit: 0 bytes in 0 blocks
==10498== total heap usage: 83 allocs, 83 frees, 10,020 bytes allocated
==10498==
==10498== All heap blocks were freed -- no leaks are possible
==10498==
==10498== For counts of detected and suppressed errors, rerun with: -v
==10498== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
OK
1 tests ok. (0 skipped)
==10497==
==10497== HEAP SUMMARY:
==10497== in use at exit: 0 bytes in 0 blocks
==10497== total heap usage: 3 allocs, 3 frees, 96 bytes allocated
==10497==
==10497== All heap blocks were freed -- no leaks are possible
==10497==
==10497== For counts of detected and suppressed errors, rerun with: -v
==10497== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
This will fix some invalid read/write:
==556== Invalid read of size 8
==556== at 0x4E4EEC6: event_queue_remove_timeout (minheap-internal.h:178)
==556== by 0x4E508AA: event_del_nolock_ (event.c:2764)
==556== by 0x4E53535: event_base_loop (event.c:3088)
==556== by 0x406FCFA: dispatch (libcrawl.c:271)
==556== by 0x402863: main (crawler.c:49)
==556== Address 0x68a3f18 is 152 bytes inside a block of size 400 free'd
==556== at 0x4C29C97: free (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==556== by 0x406F140: renew (libcrawl.c:625)
==556== by 0x4E6CDE9: evhttp_connection_cb_cleanup (http.c:1331)
==556== by 0x4E6E2B2: evhttp_connection_cb (http.c:1424)
==556== by 0x4E4DF2D: bufferevent_writecb (bufferevent_sock.c:310)
==556== by 0x4E52D1D: event_process_active_single_queue (event.c:1584)
==556== by 0x4E53676: event_base_loop (event.c:1676)
==556== by 0x406FCFA: dispatch (libcrawl.c:271)
==556== by 0x402863: main (crawler.c:49)
But this one because of some invalid write before (I guess).
It is 100% reproduced during massive crawling (because this process
has many different servers), but after spending some time for trying to
reproduce this using some simple tests/utils I gave up for a few days (I
have a lot of work to do), but I'm sending this patch as a reminder.
Just in case, I've tried next tests:
- mixing timeouts/retries
- shutdown http server and return it back
- slow dns server for first request
- sleep before accept
- hacking libevent sources to change the behaviour of http layer (so it
will go into that function which I'm insterested in).
Azat Khuzhin [Mon, 29 Sep 2014 21:34:04 +0000 (01:34 +0400)]
evdns: fail ns after we are failing/retrasmitting request
In case we are failing request (evdns_request_timeout_callback()), we
delete timeout_event in request_finished(), while just before calling
request_finished() (for failing request) there was a call to
nameserver_failed(), that add event for timeout_event, IOW we must fail
ns after request because otherwise we will not have timeout_event
actived, and we will waiting forever.
Before this patch the dns/retry_disable_when_inactive will wait forever,
after - OK.
Azat Khuzhin [Sun, 21 Sep 2014 14:29:17 +0000 (18:29 +0400)]
bufferevent_openssl: reset fd_is_set when setfd with -1 is called
Otherwise we will use old fd after close(2) called on it:
(Traces trimmed, to minimize it)
$ strace -keclose,open,socket,epoll_ctl https-client -url https://libevent.org
socket(PF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_IP) = 5
> /lib/x86_64-linux-gnu/libc-2.19.so(socket+0x7) [0xe6da7]
> /usr/lib/libevent-2.1.so.4.0.0(evutil_socket_+0x25) [0x27835]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0xe9) [0x1b1a9]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0x21f) [0x1b2df]
> /usr/lib/libevent-2.1.so.4.0.0(evutil_getaddrinfo_async_+0x65) [0x271a5]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect_hostname+0x106) [0x1b416]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0xe7) [0x39f07]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_make_request+0xb8) [0x3a218]
epoll_ctl(3, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=5, u64=5}}) = 0
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xfdd) [0x2ced]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_setfd+0x3b) [0x16d9b]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0x75) [0x1b135]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0x21f) [0x1b2df]
> /usr/lib/libevent-2.1.so.4.0.0(evutil_getaddrinfo_async_+0x65) [0x271a5]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect_hostname+0x106) [0x1b416]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0xe7) [0x39f07]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_make_request+0xb8) [0x3a218]
epoll_ctl(3, EPOLL_CTL_MOD, 5, {EPOLLIN|EPOLLOUT, {u32=5, u64=5}}) = 0
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xfee) [0x2cfe]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_setfd+0x3b) [0x16d9b]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0x75) [0x1b135]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect+0x21f) [0x1b2df]
> /usr/lib/libevent-2.1.so.4.0.0(evutil_getaddrinfo_async_+0x65) [0x271a5]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_socket_connect_hostname+0x106) [0x1b416]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0xe7) [0x39f07]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_make_request+0xb8) [0x3a218]
epoll_ctl(3, EPOLL_CTL_MOD, 5, {EPOLLOUT, {u32=5, u64=5}}) = 0
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xbbc) [0x28cc]
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xd96) [0x2aa6]
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xeb8) [0x2bc8]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x3fe) [0x1fd1e]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
epoll_ctl(3, EPOLL_CTL_DEL, 5, 7fffa1f841e0) = 0
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xbc4) [0x28d4]
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xd96) [0x2aa6]
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xeb8) [0x2bc8]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x3fe) [0x1fd1e]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
close(5) = 0
> /lib/x86_64-linux-gnu/libpthread-2.19.so(__close_nocancel+0x7) [0xeb20]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_reset_+0x55) [0x373f5]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0x1d) [0x39e3d]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x3fe) [0x1fd1e]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
epoll_ctl(3, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=5, u64=5}}) = -1 EBADF (Bad file descriptor)
) = -1 EBADF (Bad file descriptor)
/src/oss/strace-code/strace: Can't initiate libunwind: No such process
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xfdd) [0x2ced]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_setfd+0x3b) [0x16d9b]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0x14c) [0x39f6c]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x3fe) [0x1fd1e]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
/src/oss/strace-code/strace: Exit of unknown pid 28185 seen
[warn] Epoll ADD(1) on fd 5 failed. Old events were 0; read change was 1 (add); write change was 0 (none); close change was 0 (none): Bad file descriptor
epoll_ctl(3, EPOLL_CTL_ADD, 5, {EPOLLOUT, {u32=5, u64=5}}) = -1 EBADF (Bad file descriptor)
) = -1 EBADF (Bad file descriptor)
/src/oss/strace-code/strace: Can't initiate libunwind: No such process
> ...
> /usr/lib/libevent_openssl-2.1.so.4.0.0(_init+0xfee) [0x2cfe]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_setfd+0x3b) [0x16d9b]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_connect_+0x14c) [0x39f6c]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x3fe) [0x1fd1e]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
/src/oss/strace-code/strace: Exit of unknown pid 28186 seen
[warn] Epoll ADD(4) on fd 5 failed. Old events were 0; read change was 0 (none); write change was 1 (add); close change was 0 (none): Bad file descriptor
<getaddrinfo traces trimmed>
close(5) = -1 EBADF (Bad file descriptor)
) = -1 EBADF (Bad file descriptor)
/src/oss/strace-code/strace: Can't initiate libunwind: No such process
> /lib/x86_64-linux-gnu/libpthread-2.19.so(__close_nocancel+0x7) [0xeb20]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_reset_+0x55) [0x373f5]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_fail_+0xc1) [0x3aed1]
> /usr/lib/libevent-2.1.so.4.0.0(evhttp_connection_fail_+0x4a3) [0x3b2b3]
> /usr/lib/libevent-2.1.so.4.0.0(bufferevent_enable+0x192) [0x16722]
> /usr/lib/libevent-2.1.so.4.0.0(event_free+0x5df) [0x1feff]
> /usr/lib/libevent-2.1.so.4.0.0(event_base_loop+0x407) [0x20677]
/src/oss/strace-code/strace: Exit of unknown pid 28187 seen
some request failed - no idea which one though!
socket error = Bad file descriptor (9)
Before this patch:
$ sample/https-client -retries 1 -url https://libevent.org
[warn] Epoll ADD(1) on fd 6 failed. Old events were 0; read change was 1 (add); write change was 0 (none); close change was 0 (none): Bad file descriptor
[warn] Epoll ADD(4) on fd 6 failed. Old events were 0; read change was 0 (none); write change was 1 (add); close change was 0 (none): Bad file descriptor
some request failed - no idea which one though!
socket error = Bad file descriptor (9)
After this patch:
$ sample/https-client -retries 1 -url https://libevent.org
Response line: 0 (null)
Azat Khuzhin [Fri, 21 Mar 2014 13:04:58 +0000 (17:04 +0400)]
evdns: disable probing with EVDNS_BASE_DISABLE_WHEN_INACTIVE
When user install EVDNS_BASE_DISABLE_WHEN_INACTIVE flag for evdns base,
we must remove the timer that is used for probing, if current dns server
failed, otherwise it won't break the loop.
Vilmos Nebehaj [Fri, 21 Mar 2014 13:38:11 +0000 (14:38 +0100)]
Don't truncate hosts file path on Windows.
Since evutil_snprintf() (actually evutil_vsnprintf() called by it) will
make sure the buffer is null-terminated by placing a null byte at
len_out - 1, we need to pass the full length of the buffer; otherwise
the path will end in "\\host" instead of "\\hosts".
Vilmos Nebehaj [Fri, 21 Mar 2014 13:36:15 +0000 (14:36 +0100)]
Load hosts file on Windows.
Hosts files are not loaded in evdns_base_config_windows_nameservers() if
load_nameservers_with_getnetworkparams() succeeds on Windows. Parse and
load it first before setting up nameservers.