diff options
author | Anoop C S <anoopcs@redhat.com> | 2017-02-10 21:38:11 +0530 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2017-02-10 18:31:24 +0100 |
commit | 5af15532cefecb5665736f30e00960c17700d1b0 (patch) | |
tree | 16151fcfddba120c47569d39837e4851ee66ed83 | |
parent | 888a62e2c81370ab32e9bc790f12419148bd8972 (diff) | |
download | socket_wrapper-5af15532cefecb5665736f30e00960c17700d1b0.tar.gz socket_wrapper-5af15532cefecb5665736f30e00960c17700d1b0.tar.xz socket_wrapper-5af15532cefecb5665736f30e00960c17700d1b0.zip |
Avoid mutex lock wait in socket close failure
In case of absence to close a socket fd during an exit from
application we try to close the same by traversing the
socket_fds in swrap_destructor. But the early lock taken on
libc_symbol_binding_mutex inside the destructor blocks the
subsequent request for locking the same while loading
libc_close within swrap_close.
Also added a test case to verify this flaw in destructor.
Signed-off-by: Anoop C S <anoopcs@redhat.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
-rw-r--r-- | src/socket_wrapper.c | 4 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 3 | ||||
-rw-r--r-- | tests/test_close_failure.c | 50 |
3 files changed, 52 insertions, 5 deletions
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 186b696..3d468c3 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -5656,8 +5656,6 @@ void swrap_destructor(void) { struct socket_info_fd *s = socket_fds; - SWRAP_LOCK_ALL; - while (s != NULL) { swrap_close(s->fd); s = socket_fds; @@ -5671,6 +5669,4 @@ void swrap_destructor(void) if (swrap.libc.socket_handle) { dlclose(swrap.libc.socket_handle); } - - SWRAP_UNLOCK_ALL; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9292b40..c2bd799 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,7 +35,8 @@ set(SWRAP_TESTS test_echo_udp_send_recv test_echo_udp_sendmsg_recvmsg test_swrap_unit - test_max_sockets) + test_max_sockets + test_close_failure) if (HAVE_STRUCT_MSGHDR_MSG_CONTROL) set(SWRAP_TESTS ${SWRAP_TESTS} test_sendmsg_recvmsg_fd) diff --git a/tests/test_close_failure.c b/tests/test_close_failure.c new file mode 100644 index 0000000..0c9d6a7 --- /dev/null +++ b/tests/test_close_failure.c @@ -0,0 +1,50 @@ +#include "torture.h" + +#include <errno.h> +#include <stdio.h> +#include <cmocka.h> +#include <unistd.h> +#include <stdlib.h> + +static int setup(void **state) +{ + torture_setup_socket_dir(state); + + return 0; +} + +static int teardown(void **state) +{ + torture_teardown_socket_dir(state); + + return 0; +} + +static void test_close_failure(void **state) +{ + int s; + int rc; + + (void) state; /* unused */ + (void) s; /*set but not used */ + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + assert_int_not_equal(rc, -1); + + /* Do not close the socket here so that destructor + * handles it and no hang should be observed.*/ +} + +int main(void) { + int rc; + + const struct CMUnitTest close_failure_tests[] = { + cmocka_unit_test_setup_teardown(test_close_failure, + setup, teardown), + }; + + rc = cmocka_run_group_tests(close_failure_tests, NULL, NULL); + + return rc; +} |