The branch, master has been updated via ef90a76 src/socket_wrapper.c: Improve checks and debug output of socket_wrapper_dir() via 0f8e90d src/socket_wrapper.c: fix mutex fork handling via c0fb86a gitlab-ci: Add job for ThreadSanitizer via 06e423d cmake: Add ThreadSanitizer compile flags via a9d93c0 src/socket_wrapper.c: always go through swrap_bind_symbol_all() protected by pthread_once() via 5a76d73 src/socket_wrapper.c: split out _swrap_bind_symbol_generic() via 8c524f7 src/socket_wrapper.c: remove unused swrap_bind_symbol_libnsl() from e0af87f socket_wrapper.c/tests: fall back to pragma init/fini for constructor/destructor if possible
https://git.samba.org/?p=socket_wrapper.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ef90a761df3532ee45a05eb2c930769d40f5f093 Author: Andreas Schneider <a...@samba.org> Date: Thu Jan 28 20:06:11 2021 +0100 src/socket_wrapper.c: Improve checks and debug output of socket_wrapper_dir() Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 0f8e90dd7e59c473be615dee08d445dca98fdab9 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Jan 26 13:14:41 2021 +0100 src/socket_wrapper.c: fix mutex fork handling We need to use pthread_mutex_init in the child handler... See https://sourceware.org/bugzilla/show_bug.cgi?id=2745 Valgrind tools like helgrind and drd don't understand this (at least in 3.15.0), they require a pthread_mutex_unlock() in the child in order work. Pair-Programmed-With: Andreas Schneider <a...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> commit c0fb86a71418dc8610089434fda4effbc99b4c12 Author: Andreas Schneider <a...@samba.org> Date: Wed Feb 12 10:56:13 2020 +0100 gitlab-ci: Add job for ThreadSanitizer Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 06e423d0647c4a3915f8600c8ec7c8825f8f1e97 Author: Andreas Schneider <a...@samba.org> Date: Wed Feb 12 10:56:13 2020 +0100 cmake: Add ThreadSanitizer compile flags Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit a9d93c078a80bb301df3f811da7442f6e99edc68 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jan 28 14:31:31 2021 +0100 src/socket_wrapper.c: always go through swrap_bind_symbol_all() protected by pthread_once() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 5a76d7304ca655b668ee0df9f35a801121fb8d8e Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jan 28 13:11:51 2021 +0100 src/socket_wrapper.c: split out _swrap_bind_symbol_generic() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 8c524f7d35b649451888932b86a7118e99b02716 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jan 28 13:11:16 2021 +0100 src/socket_wrapper.c: remove unused swrap_bind_symbol_libnsl() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> ----------------------------------------------------------------------- Summary of changes: .gitlab-ci.yml | 24 +++ cmake/Modules/DefineCompilerFlags.cmake | 12 ++ src/socket_wrapper.c | 298 ++++++++++++++++---------------- tests/CMakeLists.txt | 9 + 4 files changed, 194 insertions(+), 149 deletions(-) Changeset truncated at 500 lines: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a28377d..c4dd3ce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,6 +77,27 @@ fedora/undefined-sanitizer: paths: - obj/ +# realpath() doesn't work with libtsan and returns EINVAL +# +# fedora/thread-sanitizer: +tumbleweed/thread-sanitizer: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=ThreadSanitizer + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + fedora/csbuild: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: @@ -225,6 +246,9 @@ tumbleweed/helgrind: when: on_failure paths: - obj/ + only: + variables: + - $VALGRIND_SUPPORTS_FORKED_MUTEXES == "yes" ubuntu/x86_64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index 3277b99..c92182d 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -34,4 +34,16 @@ if (UNIX AND NOT WIN32) CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.") + + # Activate with: -DCMAKE_BUILD_TYPE=ThreadSanitizer + set(CMAKE_C_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" + CACHE STRING "Flags used by the C compiler during THREADSANITIZER builds.") + set(CMAKE_CXX_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" + CACHE STRING "Flags used by the CXX compiler during THREADSANITIZER builds.") + set(CMAKE_SHARED_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") + set(CMAKE_MODULE_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") + set(CMAKE_EXEC_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during THREADSANITIZER builds.") endif() diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 35d61b5..89454ca 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -178,12 +178,57 @@ enum swrap_dbglvl_e { # endif #endif +#define socket_wrapper_init_mutex(m) \ + _socket_wrapper_init_mutex(m, #m) + /* Add new global locks here please */ -# define SWRAP_LOCK_ALL \ - swrap_mutex_lock(&libc_symbol_binding_mutex); \ +# define SWRAP_REINIT_ALL do { \ + size_t __i; \ + int ret; \ + ret = socket_wrapper_init_mutex(&sockets_mutex); \ + if (ret != 0) exit(-1); \ + ret = socket_wrapper_init_mutex(&socket_reset_mutex); \ + if (ret != 0) exit(-1); \ + ret = socket_wrapper_init_mutex(&first_free_mutex); \ + if (ret != 0) exit(-1); \ + for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \ + ret = socket_wrapper_init_mutex(&sockets[__i].meta.mutex); \ + if (ret != 0) exit(-1); \ + } \ + ret = socket_wrapper_init_mutex(&autobind_start_mutex); \ + if (ret != 0) exit(-1); \ + ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \ + if (ret != 0) exit(-1); \ + ret = socket_wrapper_init_mutex(&mtu_update_mutex); \ + if (ret != 0) exit(-1); \ +} while(0) -# define SWRAP_UNLOCK_ALL \ - swrap_mutex_unlock(&libc_symbol_binding_mutex); \ +# define SWRAP_LOCK_ALL do { \ + size_t __i; \ + swrap_mutex_lock(&sockets_mutex); \ + swrap_mutex_lock(&socket_reset_mutex); \ + swrap_mutex_lock(&first_free_mutex); \ + for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \ + swrap_mutex_lock(&sockets[__i].meta.mutex); \ + } \ + swrap_mutex_lock(&autobind_start_mutex); \ + swrap_mutex_lock(&pcap_dump_mutex); \ + swrap_mutex_lock(&mtu_update_mutex); \ +} while(0) + +# define SWRAP_UNLOCK_ALL do { \ + size_t __s; \ + swrap_mutex_unlock(&mtu_update_mutex); \ + swrap_mutex_unlock(&pcap_dump_mutex); \ + swrap_mutex_unlock(&autobind_start_mutex); \ + for (__s = 0; (sockets != NULL) && __s < socket_info_max; __s++) { \ + size_t __i = (socket_info_max - 1) - __s; \ + swrap_mutex_unlock(&sockets[__i].meta.mutex); \ + } \ + swrap_mutex_unlock(&first_free_mutex); \ + swrap_mutex_unlock(&socket_reset_mutex); \ + swrap_mutex_unlock(&sockets_mutex); \ +} while(0) #define SOCKET_INFO_CONTAINER(si) \ (struct socket_info_container *)(si) @@ -253,7 +298,7 @@ struct swrap_address { } sa; }; -int first_free; +static int first_free; struct socket_info { @@ -309,26 +354,23 @@ static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT; /* Hash table to map fds to corresponding socket_info index */ static int *socket_fds_idx; -/* Mutex to synchronize access to global libc.symbols */ -static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER; - /* Mutex for syncronizing port selection during swrap_auto_bind() */ -static pthread_mutex_t autobind_start_mutex; +static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex to guard the initialization of array of socket_info structures */ -static pthread_mutex_t sockets_mutex; +static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */ -static pthread_mutex_t socket_reset_mutex; +static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex to synchronize access to first free index in socket_info array */ -static pthread_mutex_t first_free_mutex; +static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex to synchronize access to packet capture dump file */ -static pthread_mutex_t pcap_dump_mutex; +static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex for synchronizing mtu value fetch*/ -static pthread_mutex_t mtu_update_mutex; +static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER; /* Function prototypes */ @@ -572,7 +614,6 @@ static char *socket_wrapper_dir(void); enum swrap_lib { SWRAP_LIBC, - SWRAP_LIBNSL, SWRAP_LIBSOCKET, }; @@ -581,8 +622,6 @@ static const char *swrap_str_lib(enum swrap_lib lib) switch (lib) { case SWRAP_LIBC: return "libc"; - case SWRAP_LIBNSL: - return "libnsl"; case SWRAP_LIBSOCKET: return "libsocket"; } @@ -620,7 +659,6 @@ static void *swrap_load_lib_handle(enum swrap_lib lib) #endif switch (lib) { - case SWRAP_LIBNSL: case SWRAP_LIBSOCKET: #ifdef HAVE_LIBSOCKET handle = swrap.libc.socket_handle; @@ -702,25 +740,27 @@ static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name) return func; } -static void swrap_mutex_lock(pthread_mutex_t *mutex) +#define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__) +static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) { int ret; ret = pthread_mutex_lock(mutex); if (ret != 0) { - SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s", - strerror(ret)); + SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s", + getpid(), getppid(), caller, line, name, strerror(ret)); } } -static void swrap_mutex_unlock(pthread_mutex_t *mutex) +#define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__) +static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) { int ret; ret = pthread_mutex_unlock(mutex); if (ret != 0) { - SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s", - strerror(ret)); + SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s", + getpid(), getppid(), caller, line, name, strerror(ret)); } } @@ -730,35 +770,18 @@ static void swrap_mutex_unlock(pthread_mutex_t *mutex) * This is an optimization to avoid locking each time we check if the symbol is * bound. */ +#define _swrap_bind_symbol_generic(lib, sym_name) do { \ + swrap.libc.symbols._libc_##sym_name.obj = \ + _swrap_bind_symbol(lib, #sym_name); \ +} while(0); + #define swrap_bind_symbol_libc(sym_name) \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap_mutex_lock(&libc_symbol_binding_mutex); \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap.libc.symbols._libc_##sym_name.obj = \ - _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \ - } \ - swrap_mutex_unlock(&libc_symbol_binding_mutex); \ - } + _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name) #define swrap_bind_symbol_libsocket(sym_name) \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap_mutex_lock(&libc_symbol_binding_mutex); \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap.libc.symbols._libc_##sym_name.obj = \ - _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \ - } \ - swrap_mutex_unlock(&libc_symbol_binding_mutex); \ - } + _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name) -#define swrap_bind_symbol_libnsl(sym_name) \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap_mutex_lock(&libc_symbol_binding_mutex); \ - if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ - swrap.libc.symbols._libc_##sym_name.obj = \ - _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \ - } \ - swrap_mutex_unlock(&libc_symbol_binding_mutex); \ - } +static void swrap_bind_symbol_all(void); /**************************************************************************** * IMPORTANT @@ -777,7 +800,7 @@ static int libc_accept4(int sockfd, socklen_t *addrlen, int flags) { - swrap_bind_symbol_libsocket(accept4); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags); } @@ -786,7 +809,7 @@ static int libc_accept4(int sockfd, static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - swrap_bind_symbol_libsocket(accept); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen); } @@ -796,14 +819,14 @@ static int libc_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - swrap_bind_symbol_libsocket(bind); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen); } static int libc_close(int fd) { - swrap_bind_symbol_libc(close); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_close.f(fd); } @@ -812,21 +835,21 @@ static int libc_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - swrap_bind_symbol_libsocket(connect); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen); } static int libc_dup(int fd) { - swrap_bind_symbol_libc(dup); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_dup.f(fd); } static int libc_dup2(int oldfd, int newfd) { - swrap_bind_symbol_libc(dup2); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_dup2.f(oldfd, newfd); } @@ -834,7 +857,7 @@ static int libc_dup2(int oldfd, int newfd) #ifdef HAVE_EVENTFD static int libc_eventfd(int count, int flags) { - swrap_bind_symbol_libc(eventfd); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_eventfd.f(count, flags); } @@ -846,7 +869,7 @@ static int libc_vfcntl(int fd, int cmd, va_list ap) void *arg; int rc; - swrap_bind_symbol_libc(fcntl); + swrap_bind_symbol_all(); arg = va_arg(ap, void *); @@ -859,7 +882,7 @@ static int libc_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - swrap_bind_symbol_libsocket(getpeername); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen); } @@ -868,7 +891,7 @@ static int libc_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - swrap_bind_symbol_libsocket(getsockname); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen); } @@ -879,7 +902,7 @@ static int libc_getsockopt(int sockfd, void *optval, socklen_t *optlen) { - swrap_bind_symbol_libsocket(getsockopt); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_getsockopt.f(sockfd, level, @@ -894,7 +917,7 @@ static int libc_vioctl(int d, unsigned long int request, va_list ap) void *arg; int rc; - swrap_bind_symbol_libc(ioctl); + swrap_bind_symbol_all(); arg = va_arg(ap, void *); @@ -905,14 +928,14 @@ static int libc_vioctl(int d, unsigned long int request, va_list ap) static int libc_listen(int sockfd, int backlog) { - swrap_bind_symbol_libsocket(listen); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_listen.f(sockfd, backlog); } static FILE *libc_fopen(const char *name, const char *mode) { - swrap_bind_symbol_libc(fopen); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_fopen.f(name, mode); } @@ -920,7 +943,7 @@ static FILE *libc_fopen(const char *name, const char *mode) #ifdef HAVE_FOPEN64 static FILE *libc_fopen64(const char *name, const char *mode) { - swrap_bind_symbol_libc(fopen64); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_fopen64.f(name, mode); } @@ -931,7 +954,7 @@ static int libc_vopen(const char *pathname, int flags, va_list ap) int mode = 0; int fd; - swrap_bind_symbol_libc(open); + swrap_bind_symbol_all(); if (flags & O_CREAT) { mode = va_arg(ap, int); @@ -959,7 +982,7 @@ static int libc_vopen64(const char *pathname, int flags, va_list ap) int mode = 0; int fd; - swrap_bind_symbol_libc(open64); + swrap_bind_symbol_all(); if (flags & O_CREAT) { mode = va_arg(ap, int); @@ -975,7 +998,7 @@ static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap) int mode = 0; int fd; - swrap_bind_symbol_libc(openat); + swrap_bind_symbol_all(); if (flags & O_CREAT) { mode = va_arg(ap, int); @@ -1004,28 +1027,28 @@ static int libc_openat(int dirfd, const char *path, int flags, ...) static int libc_pipe(int pipefd[2]) { - swrap_bind_symbol_libsocket(pipe); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_pipe.f(pipefd); } static int libc_read(int fd, void *buf, size_t count) { - swrap_bind_symbol_libc(read); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_read.f(fd, buf, count); } static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt) { - swrap_bind_symbol_libsocket(readv); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt); } static int libc_recv(int sockfd, void *buf, size_t len, int flags) { - swrap_bind_symbol_libsocket(recv); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags); } @@ -1037,7 +1060,7 @@ static int libc_recvfrom(int sockfd, struct sockaddr *src_addr, socklen_t *addrlen) { - swrap_bind_symbol_libsocket(recvfrom); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_recvfrom.f(sockfd, buf, @@ -1049,21 +1072,21 @@ static int libc_recvfrom(int sockfd, static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags) { - swrap_bind_symbol_libsocket(recvmsg); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags); } static int libc_send(int sockfd, const void *buf, size_t len, int flags) { - swrap_bind_symbol_libsocket(send); + swrap_bind_symbol_all(); return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags); } -- Socket Wrapper Repository