]> granicus.if.org Git - libevent/commitdiff
Fix an error for debug locking in dns/getaddrinfo_race_gotresolve
authorAzat Khuzhin <a3at.mail@gmail.com>
Sat, 20 Oct 2018 23:50:04 +0000 (02:50 +0300)
committerAzat Khuzhin <a3at.mail@gmail.com>
Sun, 21 Oct 2018 00:10:12 +0000 (03:10 +0300)
When there is no /etc/services file evdns_getaddrinfo() will fail (with
service="ssh") and hence it will go to then "end" label with locked
rp.lock which in case of debug locking checks will bail with:
  [err] ../evthread.c:220: Assertion lock->count == 0 failed in debug_lock_free

So add rp.locked flag, and unlock the lock before freeing it if it is in
locked state.

And here is how you can reproduce the issue:
  $ docker run -e LD_LIBRARY_PATH=$PWD/lib -e PATH=/usr/bin:/bin:$PWD/bin -v $PWD:$PWD --rm -it debian:testing regress dns/getaddrinfo_race_gotresolve
(since debian:testing does not have /etc/services)

test/regress_dns.c

index 7bbae12323300b11de69fe2e2b9f444564839670..c09a4ff5cc025a66143885072cab05f5f01f6cc6 100644 (file)
@@ -2139,6 +2139,8 @@ struct race_param
        volatile int stopping;
        void *base;
        void *dns;
+
+       int locked;
 };
 static void *
 race_base_run(void *arg)
@@ -2231,6 +2233,7 @@ getaddrinfo_race_gotresolve_test(void *arg)
        }
 
        EVLOCK_LOCK(rp.lock, 0);
+       rp.locked = 1;
 
        for (i = 0; i < n_reqs; ++i) {
                tt_assert(evdns_getaddrinfo(rp.dns, "foof.example.com", "ssh", NULL, race_gai_cb, &rp));
@@ -2256,12 +2259,15 @@ getaddrinfo_race_gotresolve_test(void *arg)
        tt_assert(EVTHREAD_COND_WAIT_TIMED(rp.bw_threads_exited_cond, rp.lock, &tv) == 0);
 
        EVLOCK_UNLOCK(rp.lock, 0);
+       rp.locked = 0;
 
        evdns_base_free(rp.dns, 1 /** fail requests */);
 
        tt_int_op(n_replies_left, ==, 0);
 
 end:
+       if (rp.locked)
+               EVLOCK_UNLOCK(rp.lock, 0);
        EVTHREAD_FREE_LOCK(rp.lock, 0);
        EVTHREAD_FREE_COND(rp.reqs_cmpl_cond);
        EVTHREAD_FREE_COND(rp.bw_threads_exited_cond);