vcom_socket_wrapper.c revision e1b749ab
1/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/*
17 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
18 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
19 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
20 *
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright
28 *    notice, this list of conditions and the following disclaimer.
29 *
30 * 2. Redistributions in binary form must reproduce the above copyright
31 *    notice, this list of conditions and the following disclaimer in the
32 *    documentation and/or other materials provided with the distribution.
33 *
34 * 3. Neither the name of the author nor the names of its contributors
35 *    may be used to endorse or promote products derived from this software
36 *    without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 */
51
52/*
53   Socket wrapper library. Passes all socket communication over
54   unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
55   is set.
56*/
57
58#include <signal.h>
59#include <dlfcn.h>
60
61#include <stdio.h>
62#include <stdarg.h>
63#include <unistd.h>
64#include <pthread.h>
65
66#include <libvcl-ldpreload/vcom_socket_wrapper.h>
67
68
69enum swrap_dbglvl_e
70{
71  SWRAP_LOG_ERROR = 0,
72  SWRAP_LOG_WARN,
73  SWRAP_LOG_DEBUG,
74  SWRAP_LOG_TRACE
75};
76
77
78/* Macros for accessing mutexes */
79#define SWRAP_LOCK(m) do { \
80        pthread_mutex_lock(&(m ## _mutex)); \
81} while(0)
82
83#define SWRAP_UNLOCK(m) do { \
84        pthread_mutex_unlock(&(m ## _mutex)); \
85} while(0)
86
87/* Add new global locks here please */
88#define SWRAP_LOCK_ALL \
89        SWRAP_LOCK(libc_symbol_binding); \
90
91#define SWRAP_UNLOCK_ALL \
92        SWRAP_UNLOCK(libc_symbol_binding); \
93
94
95
96/* The mutex for accessing the global libc.symbols */
97static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
98
99/* Function prototypes */
100
101#ifdef NDEBUG
102#define SWRAP_LOG(...)
103#else
104static void
105swrap_log (enum swrap_dbglvl_e dbglvl, const char *func,
106	   const char *format, ...)
107PRINTF_ATTRIBUTE (3, 4);
108#define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
109
110     static void
111       swrap_log (enum swrap_dbglvl_e dbglvl,
112		  const char *func, const char *format, ...)
113{
114  char buffer[1024];
115  va_list va;
116  unsigned int lvl = SWRAP_LOG_WARN;
117
118  va_start (va, format);
119  vsnprintf (buffer, sizeof (buffer), format, va);
120  va_end (va);
121
122  if (lvl >= dbglvl)
123    {
124      switch (dbglvl)
125	{
126	case SWRAP_LOG_ERROR:
127	  fprintf (stderr,
128		   "SWRAP_ERROR(%d) - %s: %s\n",
129		   (int) getpid (), func, buffer);
130	  break;
131	case SWRAP_LOG_WARN:
132	  fprintf (stderr,
133		   "SWRAP_WARN(%d) - %s: %s\n",
134		   (int) getpid (), func, buffer);
135	  break;
136	case SWRAP_LOG_DEBUG:
137	  fprintf (stderr,
138		   "SWRAP_DEBUG(%d) - %s: %s\n",
139		   (int) getpid (), func, buffer);
140	  break;
141	case SWRAP_LOG_TRACE:
142	  fprintf (stderr,
143		   "SWRAP_TRACE(%d) - %s: %s\n",
144		   (int) getpid (), func, buffer);
145	  break;
146	}
147    }
148}
149#endif
150
151
152/*********************************************************
153 * SWRAP LOADING LIBC FUNCTIONS
154 *********************************************************/
155
156#ifdef HAVE_ACCEPT4
157typedef int (*__libc_accept4) (int sockfd,
158			       struct sockaddr * addr,
159			       socklen_t * addrlen, int flags);
160#else
161typedef int (*__libc_accept) (int sockfd,
162			      struct sockaddr * addr, socklen_t * addrlen);
163#endif
164typedef int (*__libc_bind) (int sockfd,
165			    const struct sockaddr * addr, socklen_t addrlen);
166typedef int (*__libc_close) (int fd);
167typedef int (*__libc_connect) (int sockfd,
168			       const struct sockaddr * addr,
169			       socklen_t addrlen);
170
171#if 0
172/* TBD: dup and dup2 to be implemented later */
173typedef int (*__libc_dup) (int fd);
174typedef int (*__libc_dup2) (int oldfd, int newfd);
175#endif
176
177typedef int (*__libc_fcntl) (int fd, int cmd, ...);
178typedef FILE *(*__libc_fopen) (const char *name, const char *mode);
179#ifdef HAVE_FOPEN64
180typedef FILE *(*__libc_fopen64) (const char *name, const char *mode);
181#endif
182#ifdef HAVE_EVENTFD
183typedef int (*__libc_eventfd) (int count, int flags);
184#endif
185typedef int (*__libc_getpeername) (int sockfd,
186				   struct sockaddr * addr,
187				   socklen_t * addrlen);
188typedef int (*__libc_getsockname) (int sockfd,
189				   struct sockaddr * addr,
190				   socklen_t * addrlen);
191typedef int (*__libc_getsockopt) (int sockfd,
192				  int level,
193				  int optname,
194				  void *optval, socklen_t * optlen);
195typedef int (*__libc_ioctl) (int d, unsigned long int request, ...);
196typedef int (*__libc_listen) (int sockfd, int backlog);
197typedef int (*__libc_open) (const char *pathname, int flags, mode_t mode);
198#ifdef HAVE_OPEN64
199typedef int (*__libc_open64) (const char *pathname, int flags, mode_t mode);
200#endif /* HAVE_OPEN64 */
201typedef int (*__libc_openat) (int dirfd, const char *path, int flags, ...);
202typedef int (*__libc_pipe) (int pipefd[2]);
203typedef int (*__libc_read) (int fd, void *buf, size_t count);
204typedef ssize_t (*__libc_readv) (int fd, const struct iovec * iov,
205				 int iovcnt);
206typedef int (*__libc_recv) (int sockfd, void *buf, size_t len, int flags);
207typedef int (*__libc_recvfrom) (int sockfd,
208				void *buf,
209				size_t len,
210				int flags,
211				struct sockaddr * src_addr,
212				socklen_t * addrlen);
213typedef int (*__libc_recvmsg) (int sockfd, const struct msghdr * msg,
214			       int flags);
215typedef int (*__libc_send) (int sockfd, const void *buf, size_t len,
216			    int flags);
217typedef int (*__libc_sendmsg) (int sockfd, const struct msghdr * msg,
218			       int flags);
219typedef int (*__libc_sendto) (int sockfd, const void *buf, size_t len,
220			      int flags, const struct sockaddr * dst_addr,
221			      socklen_t addrlen);
222typedef int (*__libc_setsockopt) (int sockfd, int level, int optname,
223				  const void *optval, socklen_t optlen);
224#ifdef HAVE_SIGNALFD
225typedef int (*__libc_signalfd) (int fd, const sigset_t * mask, int flags);
226#endif
227typedef int (*__libc_socket) (int domain, int type, int protocol);
228typedef int (*__libc_socketpair) (int domain, int type, int protocol,
229				  int sv[2]);
230#ifdef HAVE_TIMERFD_CREATE
231typedef int (*__libc_timerfd_create) (int clockid, int flags);
232#endif
233typedef ssize_t (*__libc_write) (int fd, const void *buf, size_t count);
234typedef ssize_t (*__libc_writev) (int fd, const struct iovec * iov,
235				  int iovcnt);
236
237typedef int (*__libc_shutdown) (int fd, int how);
238
239typedef int (*__libc_select) (int __nfds, fd_set * __restrict __readfds,
240			      fd_set * __restrict __writefds,
241			      fd_set * __restrict __exceptfds,
242			      struct timeval * __restrict __timeout);
243
244#ifdef __USE_XOPEN2K
245typedef int (*__libc_pselect) (int __nfds, fd_set * __restrict __readfds,
246			       fd_set * __restrict __writefds,
247			       fd_set * __restrict __exceptfds,
248			       const struct timespec * __restrict __timeout,
249			       const __sigset_t * __restrict __sigmask);
250#endif
251
252#define SWRAP_SYMBOL_ENTRY(i) \
253        union { \
254                __libc_##i f; \
255                void *obj; \
256        } _libc_##i
257
258struct swrap_libc_symbols
259{
260#ifdef HAVE_ACCEPT4
261  SWRAP_SYMBOL_ENTRY (accept4);
262#else
263  SWRAP_SYMBOL_ENTRY (accept);
264#endif
265  SWRAP_SYMBOL_ENTRY (bind);
266  SWRAP_SYMBOL_ENTRY (close);
267  SWRAP_SYMBOL_ENTRY (connect);
268#if 0
269  /* TBD: dup and dup2 to be implemented later */
270  SWRAP_SYMBOL_ENTRY (dup);
271  SWRAP_SYMBOL_ENTRY (dup2);
272#endif
273  SWRAP_SYMBOL_ENTRY (fcntl);
274  SWRAP_SYMBOL_ENTRY (fopen);
275#ifdef HAVE_FOPEN64
276  SWRAP_SYMBOL_ENTRY (fopen64);
277#endif
278#ifdef HAVE_EVENTFD
279  SWRAP_SYMBOL_ENTRY (eventfd);
280#endif
281  SWRAP_SYMBOL_ENTRY (getpeername);
282  SWRAP_SYMBOL_ENTRY (getsockname);
283  SWRAP_SYMBOL_ENTRY (getsockopt);
284  SWRAP_SYMBOL_ENTRY (ioctl);
285  SWRAP_SYMBOL_ENTRY (listen);
286  SWRAP_SYMBOL_ENTRY (open);
287#ifdef HAVE_OPEN64
288  SWRAP_SYMBOL_ENTRY (open64);
289#endif
290  SWRAP_SYMBOL_ENTRY (openat);
291  SWRAP_SYMBOL_ENTRY (pipe);
292  SWRAP_SYMBOL_ENTRY (read);
293  SWRAP_SYMBOL_ENTRY (readv);
294  SWRAP_SYMBOL_ENTRY (recv);
295  SWRAP_SYMBOL_ENTRY (recvfrom);
296  SWRAP_SYMBOL_ENTRY (recvmsg);
297  SWRAP_SYMBOL_ENTRY (send);
298  SWRAP_SYMBOL_ENTRY (sendmsg);
299  SWRAP_SYMBOL_ENTRY (sendto);
300  SWRAP_SYMBOL_ENTRY (setsockopt);
301#ifdef HAVE_SIGNALFD
302  SWRAP_SYMBOL_ENTRY (signalfd);
303#endif
304  SWRAP_SYMBOL_ENTRY (socket);
305  SWRAP_SYMBOL_ENTRY (socketpair);
306#ifdef HAVE_TIMERFD_CREATE
307  SWRAP_SYMBOL_ENTRY (timerfd_create);
308#endif
309  SWRAP_SYMBOL_ENTRY (write);
310  SWRAP_SYMBOL_ENTRY (writev);
311
312  SWRAP_SYMBOL_ENTRY (shutdown);
313  SWRAP_SYMBOL_ENTRY (select);
314#ifdef __USE_XOPEN2K
315  SWRAP_SYMBOL_ENTRY (pselect);
316#endif
317};
318
319struct swrap
320{
321  struct
322  {
323    void *handle;
324    void *socket_handle;
325    struct swrap_libc_symbols symbols;
326  } libc;
327};
328
329static struct swrap swrap;
330
331#define LIBC_NAME "libc.so"
332
333enum swrap_lib
334{
335  SWRAP_LIBC,
336};
337
338#ifndef NDEBUG
339static const char *
340swrap_str_lib (enum swrap_lib lib)
341{
342  switch (lib)
343    {
344    case SWRAP_LIBC:
345      return "libc";
346    }
347
348  /* Compiler would warn us about unhandled enum value if we get here */
349  return "unknown";
350}
351#endif
352
353static void *
354swrap_load_lib_handle (enum swrap_lib lib)
355{
356  int flags = RTLD_LAZY;
357  void *handle = NULL;
358  int i;
359
360#ifdef RTLD_DEEPBIND
361  flags |= RTLD_DEEPBIND;
362#endif
363
364  switch (lib)
365    {
366    case SWRAP_LIBC:
367      handle = swrap.libc.handle;
368#ifdef LIBC_SO
369      if (handle == NULL)
370	{
371	  handle = dlopen (LIBC_SO, flags);
372
373	  swrap.libc.handle = handle;
374	}
375#endif
376      if (handle == NULL)
377	{
378	  for (i = 10; i >= 0; i--)
379	    {
380	      char soname[256] = { 0 };
381
382	      snprintf (soname, sizeof (soname), "libc.so.%d", i);
383	      handle = dlopen (soname, flags);
384	      if (handle != NULL)
385		{
386		  break;
387		}
388	    }
389
390	  swrap.libc.handle = handle;
391	}
392      break;
393    }
394
395  if (handle == NULL)
396    {
397      SWRAP_LOG (SWRAP_LOG_ERROR,
398		 "Failed to dlopen library: %s\n", dlerror ());
399      exit (-1);
400    }
401
402  return handle;
403}
404
405static void *
406_swrap_bind_symbol (enum swrap_lib lib, const char *fn_name)
407{
408  void *handle;
409  void *func;
410
411  handle = swrap_load_lib_handle (lib);
412
413  func = dlsym (handle, fn_name);
414  if (func == NULL)
415    {
416      SWRAP_LOG (SWRAP_LOG_ERROR,
417		 "Failed to find %s: %s\n", fn_name, dlerror ());
418      exit (-1);
419    }
420
421  SWRAP_LOG (SWRAP_LOG_TRACE,
422	     "Loaded %s from %s", fn_name, swrap_str_lib (lib));
423
424  return func;
425}
426
427#define swrap_bind_symbol_libc(sym_name) \
428        SWRAP_LOCK(libc_symbol_binding); \
429        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
430                swrap.libc.symbols._libc_##sym_name.obj = \
431                        _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
432        } \
433        SWRAP_UNLOCK(libc_symbol_binding)
434
435/*
436 * IMPORTANT
437 *
438 * Functions especially from libc need to be loaded individually, you can't load
439 * all at once or gdb will segfault at startup. The same applies to valgrind and
440 * has probably something todo with with the linker.
441 * So we need load each function at the point it is called the first time.
442 */
443#ifdef HAVE_ACCEPT4
444int
445libc_accept4 (int sockfd,
446	      struct sockaddr *addr, socklen_t * addrlen, int flags)
447{
448  swrap_bind_symbol_libc (accept4);
449
450  return swrap.libc.symbols._libc_accept4.f (sockfd, addr, addrlen, flags);
451}
452
453#else /* HAVE_ACCEPT4 */
454
455int
456libc_accept (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
457{
458  swrap_bind_symbol_libc (accept);
459
460  return swrap.libc.symbols._libc_accept.f (sockfd, addr, addrlen);
461}
462#endif /* HAVE_ACCEPT4 */
463
464int
465libc_bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
466{
467  swrap_bind_symbol_libc (bind);
468
469  return swrap.libc.symbols._libc_bind.f (sockfd, addr, addrlen);
470}
471
472int
473libc_close (int fd)
474{
475  swrap_bind_symbol_libc (close);
476
477  return swrap.libc.symbols._libc_close.f (fd);
478}
479
480int
481libc_connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
482{
483  swrap_bind_symbol_libc (connect);
484
485  return swrap.libc.symbols._libc_connect.f (sockfd, addr, addrlen);
486}
487
488#if 0
489/* TBD: dup and dup2 to be implemented later */
490int
491libc_dup (int fd)
492{
493  swrap_bind_symbol_libc (dup);
494
495  return swrap.libc.symbols._libc_dup.f (fd);
496}
497
498int
499libc_dup2 (int oldfd, int newfd)
500{
501  swrap_bind_symbol_libc (dup2);
502
503  return swrap.libc.symbols._libc_dup2.f (oldfd, newfd);
504}
505#endif
506
507#ifdef HAVE_EVENTFD
508int
509libc_eventfd (int count, int flags)
510{
511  swrap_bind_symbol_libc (eventfd);
512
513  return swrap.libc.symbols._libc_eventfd.f (count, flags);
514}
515#endif
516
517DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int
518libc_vfcntl (int fd, int cmd, va_list ap)
519{
520  long int args[4];
521  int rc;
522  int i;
523
524  swrap_bind_symbol_libc (fcntl);
525
526  for (i = 0; i < 4; i++)
527    {
528      args[i] = va_arg (ap, long int);
529    }
530
531  rc = swrap.libc.symbols._libc_fcntl.f (fd,
532					 cmd,
533					 args[0], args[1], args[2], args[3]);
534
535  return rc;
536}
537
538int
539libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
540{
541  swrap_bind_symbol_libc (getpeername);
542
543  return swrap.libc.symbols._libc_getpeername.f (sockfd, addr, addrlen);
544}
545
546int
547libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
548{
549  swrap_bind_symbol_libc (getsockname);
550
551  return swrap.libc.symbols._libc_getsockname.f (sockfd, addr, addrlen);
552}
553
554int
555libc_getsockopt (int sockfd,
556		 int level, int optname, void *optval, socklen_t * optlen)
557{
558  swrap_bind_symbol_libc (getsockopt);
559
560  return swrap.libc.symbols._libc_getsockopt.f (sockfd,
561						level,
562						optname, optval, optlen);
563}
564
565int
566libc_listen (int sockfd, int backlog)
567{
568  swrap_bind_symbol_libc (listen);
569
570  return swrap.libc.symbols._libc_listen.f (sockfd, backlog);
571}
572
573int
574libc_read (int fd, void *buf, size_t count)
575{
576  swrap_bind_symbol_libc (read);
577
578  return swrap.libc.symbols._libc_read.f (fd, buf, count);
579}
580
581int
582libc_recv (int sockfd, void *buf, size_t len, int flags)
583{
584  swrap_bind_symbol_libc (recv);
585
586  return swrap.libc.symbols._libc_recv.f (sockfd, buf, len, flags);
587}
588
589int
590libc_recvfrom (int sockfd,
591	       void *buf,
592	       size_t len,
593	       int flags, struct sockaddr *src_addr, socklen_t * addrlen)
594{
595  swrap_bind_symbol_libc (recvfrom);
596
597  return swrap.libc.symbols._libc_recvfrom.f (sockfd,
598					      buf,
599					      len, flags, src_addr, addrlen);
600}
601
602int
603libc_recvmsg (int sockfd, struct msghdr *msg, int flags)
604{
605  swrap_bind_symbol_libc (recvmsg);
606
607  return swrap.libc.symbols._libc_recvmsg.f (sockfd, msg, flags);
608}
609
610int
611libc_send (int sockfd, const void *buf, size_t len, int flags)
612{
613  swrap_bind_symbol_libc (send);
614
615  return swrap.libc.symbols._libc_send.f (sockfd, buf, len, flags);
616}
617
618int
619libc_sendmsg (int sockfd, const struct msghdr *msg, int flags)
620{
621  swrap_bind_symbol_libc (sendmsg);
622
623  return swrap.libc.symbols._libc_sendmsg.f (sockfd, msg, flags);
624}
625
626int
627libc_sendto (int sockfd,
628	     const void *buf,
629	     size_t len,
630	     int flags, const struct sockaddr *dst_addr, socklen_t addrlen)
631{
632  swrap_bind_symbol_libc (sendto);
633
634  return swrap.libc.symbols._libc_sendto.f (sockfd,
635					    buf,
636					    len, flags, dst_addr, addrlen);
637}
638
639int
640libc_setsockopt (int sockfd,
641		 int level, int optname, const void *optval, socklen_t optlen)
642{
643  swrap_bind_symbol_libc (setsockopt);
644
645  return swrap.libc.symbols._libc_setsockopt.f (sockfd,
646						level,
647						optname, optval, optlen);
648}
649
650int
651libc_socket (int domain, int type, int protocol)
652{
653  swrap_bind_symbol_libc (socket);
654
655  return swrap.libc.symbols._libc_socket.f (domain, type, protocol);
656}
657
658int
659libc_socketpair (int domain, int type, int protocol, int sv[2])
660{
661  swrap_bind_symbol_libc (socketpair);
662
663  return swrap.libc.symbols._libc_socketpair.f (domain, type, protocol, sv);
664}
665
666ssize_t
667libc_write (int fd, const void *buf, size_t count)
668{
669  swrap_bind_symbol_libc (write);
670
671  return swrap.libc.symbols._libc_write.f (fd, buf, count);
672}
673
674int
675libc_shutdown (int fd, int how)
676{
677  swrap_bind_symbol_libc (shutdown);
678
679  return swrap.libc.symbols._libc_shutdown.f (fd, how);
680}
681
682int
683libc_select (int __nfds, fd_set * __restrict __readfds,
684	     fd_set * __restrict __writefds,
685	     fd_set * __restrict __exceptfds,
686	     struct timeval *__restrict __timeout)
687{
688  swrap_bind_symbol_libc (select);
689
690  return swrap.libc.symbols._libc_select.f (__nfds, __readfds,
691					    __writefds,
692					    __exceptfds, __timeout);
693}
694
695#ifdef __USE_XOPEN2K
696int
697libc_pselect (int __nfds, fd_set * __restrict __readfds,
698	      fd_set * __restrict __writefds,
699	      fd_set * __restrict __exceptfds,
700	      const struct timespec *__restrict __timeout,
701	      const __sigset_t * __restrict __sigmask)
702{
703  swrap_bind_symbol_libc (pselect);
704
705  return swrap.libc.symbols._libc_pselect.f (__nfds, __readfds,
706					     __writefds,
707					     __exceptfds,
708					     __timeout, __sigmask);
709}
710#endif
711
712static void
713swrap_thread_prepare (void)
714{
715  SWRAP_LOCK_ALL;
716}
717
718static void
719swrap_thread_parent (void)
720{
721  SWRAP_UNLOCK_ALL;
722}
723
724static void
725swrap_thread_child (void)
726{
727  SWRAP_UNLOCK_ALL;
728}
729
730/****************************
731 * CONSTRUCTOR
732 ***************************/
733void
734swrap_constructor (void)
735{
736  /*
737   * If we hold a lock and the application forks, then the child
738   * is not able to unlock the mutex and we are in a deadlock.
739   * This should prevent such deadlocks.
740   */
741  pthread_atfork (&swrap_thread_prepare,
742		  &swrap_thread_parent, &swrap_thread_child);
743}
744
745/****************************
746 * DESTRUCTOR
747 ***************************/
748
749/*
750 * This function is called when the library is unloaded and makes sure that
751 * sockets get closed and the unix file for the socket are unlinked.
752 */
753void
754swrap_destructor (void)
755{
756  if (swrap.libc.handle != NULL)
757    {
758      dlclose (swrap.libc.handle);
759    }
760  if (swrap.libc.socket_handle)
761    {
762      dlclose (swrap.libc.socket_handle);
763    }
764}
765
766/*
767 * fd.io coding-style-patch-verification: ON
768 *
769 * Local Variables:
770 * eval: (c-set-style "gnu")
771 * End:
772 */
773