Hello community,

here is the log from the commit of package socket_wrapper for openSUSE:Factory 
checked in at 2017-12-05 01:30:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/socket_wrapper (Old)
 and      /work/SRC/openSUSE:Factory/.socket_wrapper.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "socket_wrapper"

Tue Dec  5 01:30:25 2017 rev:8 rq:548058 version:1.1.9

Changes:
--------
--- /work/SRC/openSUSE:Factory/socket_wrapper/socket_wrapper.changes    
2017-10-17 01:51:55.272111923 +0200
+++ /work/SRC/openSUSE:Factory/.socket_wrapper.new/socket_wrapper.changes       
2017-12-05 01:30:27.432820946 +0100
@@ -1,0 +2,6 @@
+Mon Dec  4 11:22:22 UTC 2017 - [email protected]
+
+- Update to version 1.1.9
+  * Fixed thread - signal deadlock issue
+
+-------------------------------------------------------------------

Old:
----
  socket_wrapper-1.1.8.tar.gz

New:
----
  socket_wrapper-1.1.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ socket_wrapper.spec ++++++
--- /var/tmp/diff_new_pack.bR4fzE/_old  2017-12-05 01:30:28.220792320 +0100
+++ /var/tmp/diff_new_pack.bR4fzE/_new  2017-12-05 01:30:28.224792174 +0100
@@ -24,7 +24,7 @@
 ############################# NOTE ##################################
 
 Name:           socket_wrapper
-Version:        1.1.8
+Version:        1.1.9
 Release:        0
 Summary:        A library passing all socket communications trough Unix sockets
 License:        BSD-3-Clause

++++++ socket_wrapper-1.1.8.tar.gz -> socket_wrapper-1.1.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/CMakeLists.txt 
new/socket_wrapper-1.1.9/CMakeLists.txt
--- old/socket_wrapper-1.1.8/CMakeLists.txt     2017-10-12 16:47:44.000000000 
+0200
+++ new/socket_wrapper-1.1.9/CMakeLists.txt     2017-12-04 10:21:00.000000000 
+0100
@@ -8,7 +8,7 @@
 
 set(APPLICATION_VERSION_MAJOR "1")
 set(APPLICATION_VERSION_MINOR "1")
-set(APPLICATION_VERSION_PATCH "8")
+set(APPLICATION_VERSION_PATCH "9")
 
 set(APPLICATION_VERSION 
"${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
 
@@ -19,7 +19,7 @@
 #     Increment AGE. Set REVISION to 0
 #   If the source code was changed, but there were no interface changes:
 #     Increment REVISION.
-set(LIBRARY_VERSION "0.1.8")
+set(LIBRARY_VERSION "0.1.9")
 set(LIBRARY_SOVERSION "0")
 
 # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is 
checked
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/ChangeLog 
new/socket_wrapper-1.1.9/ChangeLog
--- old/socket_wrapper-1.1.8/ChangeLog  2017-10-13 08:18:59.000000000 +0200
+++ new/socket_wrapper-1.1.9/ChangeLog  2017-12-04 10:21:00.000000000 +0100
@@ -1,6 +1,9 @@
 ChangeLog
 ==========
 
+version 1.1.9 (released 2017-12-04)
+  * Fixed thread - signal deadlock issue
+
 version 1.1.8 (released 2017-10-13)
   * Added support for openat()
   * Added support for open64() and fopen64()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/src/socket_wrapper.c 
new/socket_wrapper-1.1.9/src/socket_wrapper.c
--- old/socket_wrapper-1.1.8/src/socket_wrapper.c       2017-09-07 
07:57:43.000000000 +0200
+++ new/socket_wrapper-1.1.9/src/socket_wrapper.c       2017-12-04 
10:20:52.000000000 +0100
@@ -671,37 +671,46 @@
 }
 
 #define swrap_bind_symbol_libc(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
 #define swrap_bind_symbol_libsocket(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); 
\
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
 #define swrap_bind_symbol_libnsl(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
-/*
- * IMPORTANT
+/****************************************************************************
+ *                               IMPORTANT
+ ****************************************************************************
  *
- * Functions especially from libc need to be loaded individually, you can't 
load
- * all at once or gdb will segfault at startup. The same applies to valgrind 
and
- * has probably something todo with with the linker.
- * So we need load each function at the point it is called the first time.
- */
+ * Functions especially from libc need to be loaded individually, you can't
+ * load all at once or gdb will segfault at startup. The same applies to
+ * valgrind and has probably something todo with with the linker.  So we need
+ * load each function at the point it is called the first time.
+ *
+ ****************************************************************************/
+
 #ifdef HAVE_ACCEPT4
 static int libc_accept4(int sockfd,
                        struct sockaddr *addr,
@@ -1077,6 +1086,59 @@
        return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
 }
 
+/* DO NOT call this function during library initialization! */
+static void swrap_bind_symbol_all(void)
+{
+#ifdef HAVE_ACCEPT4
+       swrap_bind_symbol_libsocket(accept4);
+#else
+       swrap_bind_symbol_libsocket(accept);
+#endif
+       swrap_bind_symbol_libsocket(bind);
+       swrap_bind_symbol_libc(close);
+       swrap_bind_symbol_libsocket(connect);
+       swrap_bind_symbol_libc(dup);
+       swrap_bind_symbol_libc(dup2);
+       swrap_bind_symbol_libc(fcntl);
+       swrap_bind_symbol_libc(fopen);
+#ifdef HAVE_FOPEN64
+       swrap_bind_symbol_libc(fopen64);
+#endif
+#ifdef HAVE_EVENTFD
+       swrap_bind_symbol_libc(eventfd);
+#endif
+       swrap_bind_symbol_libsocket(getpeername);
+       swrap_bind_symbol_libsocket(getsockname);
+       swrap_bind_symbol_libsocket(getsockopt);
+       swrap_bind_symbol_libc(ioctl);
+       swrap_bind_symbol_libsocket(listen);
+       swrap_bind_symbol_libc(open);
+#ifdef HAVE_OPEN64
+       swrap_bind_symbol_libc(open64);
+#endif
+       swrap_bind_symbol_libc(openat);
+       swrap_bind_symbol_libsocket(pipe);
+       swrap_bind_symbol_libc(read);
+       swrap_bind_symbol_libsocket(readv);
+       swrap_bind_symbol_libsocket(recv);
+       swrap_bind_symbol_libsocket(recvfrom);
+       swrap_bind_symbol_libsocket(recvmsg);
+       swrap_bind_symbol_libsocket(send);
+       swrap_bind_symbol_libsocket(sendmsg);
+       swrap_bind_symbol_libsocket(sendto);
+       swrap_bind_symbol_libsocket(setsockopt);
+#ifdef HAVE_SIGNALFD
+       swrap_bind_symbol_libsocket(signalfd);
+#endif
+       swrap_bind_symbol_libsocket(socket);
+       swrap_bind_symbol_libsocket(socketpair);
+#ifdef HAVE_TIMERFD_CREATE
+       swrap_bind_symbol_libc(timerfd_create);
+#endif
+       swrap_bind_symbol_libc(write);
+       swrap_bind_symbol_libsocket(writev);
+}
+
 /*********************************************************
  * SWRAP HELPER FUNCTIONS
  *********************************************************/
@@ -1523,7 +1585,7 @@
 
                if (addr == 0) {
                        /* 0.0.0.0 */
-                       is_bcast = 0;
+                       is_bcast = 0;
                        type = d_type;
                        iface = socket_wrapper_default_iface();
                } else if (a_type && addr == 0xFFFFFFFF) {
@@ -2344,7 +2406,7 @@
        if (fd != -1) {
                struct swrap_file_hdr file_hdr;
                file_hdr.magic          = 0xA1B2C3D4;
-               file_hdr.version_major  = 0x0002;       
+               file_hdr.version_major  = 0x0002;
                file_hdr.version_minor  = 0x0004;
                file_hdr.timezone       = 0x00000000;
                file_hdr.sigfigs        = 0x00000000;
@@ -5835,6 +5897,15 @@
 
 static void swrap_thread_prepare(void)
 {
+       /*
+        * This function should only be called here!!
+        *
+        * We bind all symobls to avoid deadlocks of the fork is
+        * interrupted by a signal handler using a symbol of this
+        * library.
+        */
+       swrap_bind_symbol_all();
+
        SWRAP_LOCK_ALL;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/tests/CMakeLists.txt 
new/socket_wrapper-1.1.9/tests/CMakeLists.txt
--- old/socket_wrapper-1.1.8/tests/CMakeLists.txt       2017-09-07 
07:57:43.000000000 +0200
+++ new/socket_wrapper-1.1.9/tests/CMakeLists.txt       2017-12-04 
10:20:57.000000000 +0100
@@ -37,7 +37,8 @@
     test_echo_udp_sendmsg_recvmsg
     test_swrap_unit
     test_max_sockets
-    test_close_failure)
+    test_close_failure
+    test_fork_thread_deadlock)
 
 if (HAVE_STRUCT_MSGHDR_MSG_CONTROL)
     set(SWRAP_TESTS ${SWRAP_TESTS} test_sendmsg_recvmsg_fd)
@@ -60,3 +61,8 @@
                 ENVIRONMENT LD_PRELOAD=${SOCKET_WRAPPER_LOCATION})
     endif()
 endforeach()
+
+# test_fork_pthread
+add_library(thread_deadlock SHARED thread_deadlock.c)
+target_link_libraries(thread_deadlock ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(test_fork_thread_deadlock thread_deadlock)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/tests/test_echo_tcp_bind.c 
new/socket_wrapper-1.1.9/tests/test_echo_tcp_bind.c
--- old/socket_wrapper-1.1.8/tests/test_echo_tcp_bind.c 2016-10-20 
09:01:42.000000000 +0200
+++ new/socket_wrapper-1.1.9/tests/test_echo_tcp_bind.c 2017-12-04 
10:20:41.000000000 +0100
@@ -143,7 +143,7 @@
         * Finally, success binding a new IPv4 address.
         */
        addr_in = (struct torture_address) {
-               .sa_socklen = sizeof(struct sockaddr_un),
+               .sa_socklen = sizeof(struct sockaddr_in),
                .sa.in = (struct sockaddr_in) {
                        .sin_family = AF_INET,
                },
@@ -156,7 +156,7 @@
        assert_return_code(rc, errno);
 
        addr_in = (struct torture_address) {
-               .sa_socklen = sizeof(struct sockaddr_un),
+               .sa_socklen = sizeof(struct sockaddr_in),
                .sa.in = (struct sockaddr_in) {
                        .sin_family = AF_INET,
                        .sin_port = htons(torture_server_port()),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/socket_wrapper-1.1.8/tests/test_fork_thread_deadlock.c 
new/socket_wrapper-1.1.9/tests/test_fork_thread_deadlock.c
--- old/socket_wrapper-1.1.8/tests/test_fork_thread_deadlock.c  1970-01-01 
01:00:00.000000000 +0100
+++ new/socket_wrapper-1.1.9/tests/test_fork_thread_deadlock.c  2017-12-04 
10:20:57.000000000 +0100
@@ -0,0 +1,98 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+
+/*
+ * This reproduces and issue if we get a signal after the pthread_atfork()
+ * prepare function of socket wrapper has been called.
+ *
+ * The order how pthread_atfork() handlers are set up is:
+ *   -> application
+ *   -> preloaded libraries
+ *   -> libraries
+ *
+ * We have a library called thread_deadlock.
+ *
+ * This library registers a thread_deadlock_prepare() function via
+ * pthread_atfork().
+ *
+ * So pthread_atfork() registers the prepare function in the follow order:
+ *   -> swrap_thread_prepare()
+ *   -> thread_deadlock_prepare()
+ *
+ * In this test we fork and the swrap_thread_prepare() locks the mutex for
+ * symbol binding.
+ * Then thread_deadlock_prepare() is called which sends a signal to the parent
+ * process of this test. The signal triggers the signal handler below.
+ *
+ * When we call write() in the signal handler, we will try to bind the libc 
symbol
+ * and want to lock the symbol binding mutex. As it is already locked we run 
into
+ * a deadlock.
+ */
+
+static void test_swrap_signal_handler(int signum)
+{
+       fprintf(stderr, "PID: %d, SIGNUM: %d\n", getpid(), signum);
+       write(1, "DEADLOCK?\n", 10);
+}
+
+static void test_swrap_fork_pthread(void **state)
+{
+       pid_t pid;
+       struct sigaction act = {
+               .sa_handler = test_swrap_signal_handler,
+               .sa_flags = 0,
+       };
+
+       (void)state; /* unused */
+
+       sigemptyset(&act.sa_mask);
+       sigaction(SIGUSR1, &act, NULL);
+
+       pid = fork();
+       assert_return_code(pid, errno);
+
+       /* child */
+       if (pid == 0) {
+               exit(0);
+       }
+
+       /* parent */
+       if (pid > 0) {
+               pid_t child_pid;
+               int wstatus = -1;
+
+               child_pid = waitpid(-1, &wstatus, 0);
+               assert_return_code(child_pid, errno);
+
+               assert_true(WIFEXITED(wstatus));
+
+               assert_int_equal(WEXITSTATUS(wstatus), 0);
+       }
+}
+
+int main(void)
+{
+       int rc;
+
+       const struct CMUnitTest swrap_tests[] = {
+               cmocka_unit_test(test_swrap_fork_pthread),
+       };
+
+       rc = cmocka_run_group_tests(swrap_tests, NULL, NULL);
+
+       return rc;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/socket_wrapper-1.1.8/tests/thread_deadlock.c 
new/socket_wrapper-1.1.9/tests/thread_deadlock.c
--- old/socket_wrapper-1.1.8/tests/thread_deadlock.c    1970-01-01 
01:00:00.000000000 +0100
+++ new/socket_wrapper-1.1.9/tests/thread_deadlock.c    2017-12-04 
10:20:57.000000000 +0100
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017      Andreas Schneider <[email protected]>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <pthread.h>
+
+#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
+#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
+#else
+#define CONSTRUCTOR_ATTRIBUTE
+#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
+
+void thread_deadlock_constructor(void) CONSTRUCTOR_ATTRIBUTE;
+
+static void thread_deadlock_prepare(void)
+{
+       pthread_kill(pthread_self(), SIGUSR1);
+       return;
+}
+
+static void thread_deadlock_parent(void)
+{
+       return;
+}
+
+static void thread_deadlock_child(void)
+{
+       return;
+}
+
+void thread_deadlock_constructor(void)
+{
+       pthread_atfork(&thread_deadlock_prepare,
+                      &thread_deadlock_parent,
+                      &thread_deadlock_child);
+}


Reply via email to