Re: Compiling libpq with VisualC - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Compiling libpq with VisualC
Date
Msg-id 200406110340.i5B3ebU16247@candle.pha.pa.us
Whole thread Raw
In response to Re: Compiling libpq with VisualC  (Andreas Pflug <pgadmin@pse-consulting.de>)
Responses Re: Compiling libpq with VisualC
List pgsql-patches
I have looked over this patch.  I noticed this:

    -static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
    -
    +        static pthread_mutex_t init_mutex;
    +        static int mutex_initialized = 0;
    +        if (!mutex_initialized)
    +        {
    +                mutex_initialized = 1;
    +                pthread_mutex_init(&init_mutex, NULL);
    +        }

While this might work using your pthread compatibility implementation
using CreateMutex(), it will not work on a native pthread implementation
because you can only call pthread_mutex_init() once.  Your code allows
two threads to both call it.

Now, how to fix it?  You need some kind of pthread_once() call or
somehow set up a critical section that will prevent two threads from
doing the initialization, but there is no method using your API to
create the critical section without creating a lock first.

I am thinking we need to put your initialization code in #ifdef WIN32
and keep the native pthread code unchanged.

Also, do you not have the problem with SIGPIPE from send(), so you don't
need set/get_thread_specific()?

---------------------------------------------------------------------------

Andreas Pflug wrote:
> The appended patch implements ENABLE_THREAD_SAFETY for win32 compiled
> with Visual C. Two additional files will supply the needed pthread stuff.
>
> There's no SIGPIPE for native win32, so there are some #IFNDEF WIN32 to
> skip installing a signal handler for this. I'm not sure if this is going
> to show conflicts for CYGWIN or other unix-like builds on win32
> platforms, i.e. if WIN32 is defined in such cases or not; please check.
>
> Note: the previously posted win32.mak patch is superseded by this.
>
> Regards,
> Andreas

> Index: win32.mak
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.mak,v
> retrieving revision 1.23
> diff -u -r1.23 win32.mak
> --- win32.mak    3 Jun 2004 00:11:13 -0000    1.23
> +++ win32.mak    4 Jun 2004 13:26:39 -0000
> @@ -74,19 +74,25 @@
>      -@erase "$(OUTDIR)\$(OUTFILENAME)dll.lib"
>      -@erase "$(INTDIR)\wchar.obj"
>      -@erase "$(INTDIR)\encnames.obj"
> +    -@erase "$(INTDIR)\pthread-win32.obj"
>
>
>
> -config: ..\..\include\pg_config.h
> +config: ..\..\include\pg_config.h pthread.h pg_config_paths.h
>
>  ..\..\include\pg_config.h: ..\..\include\pg_config.h.win32
>      copy ..\..\include\pg_config.h.win32 ..\..\include\pg_config.h
>
> +pthread.h: pthread.h.win32
> +    copy pthread.h.win32 pthread.h
> +
> +pg_config_paths.h: win32.mak
> +    echo #define SYSCONFDIR "" >pg_config_paths.h
>
>  "$(OUTDIR)" :
>      if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
>
> -CPP_PROJ=/nologo /W3 /GX $(OPT) /I "..\..\include" /D "FRONTEND" $(DEBUGDEF) /D\
> +CPP_PROJ=/nologo /W3 /GX $(OPT) /I "..\..\include" /I. /D "FRONTEND" $(DEBUGDEF) /D\
>   "WIN32" /D "_WINDOWS" /Fp"$(INTDIR)\libpq.pch" /YX\
>   /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c  /D "HAVE_VSNPRINTF" /D "HAVE_STRDUP"
>
> @@ -95,6 +101,10 @@
>  SSL_LIBS=ssleay32.lib libeay32.lib gdi32.lib
>  !ENDIF
>
> +!IFDEF ENABLE_THREAD_SAFETY
> +CPP_PROJ=$(CPP_PROJ) /D ENABLE_THREAD_SAFETY
> +!ENDIF
> +
>  CPP_SBRS=.
>
>  LIB32=link.exe -lib
> @@ -121,7 +131,8 @@
>      "$(INTDIR)\fe-secure.obj" \
>      "$(INTDIR)\pqexpbuffer.obj" \
>      "$(INTDIR)\wchar.obj" \
> -    "$(INTDIR)\encnames.obj"
> +    "$(INTDIR)\encnames.obj" \
> +    "$(INTDIR)\pthread-win32.obj"
>
>
>  RSC_PROJ=/l 0x409 /fo"$(INTDIR)\libpq.res"
> Index: fe-connect.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
> retrieving revision 1.272
> diff -u -r1.272 fe-connect.c
> --- fe-connect.c    3 Jun 2004 00:07:38 -0000    1.272
> +++ fe-connect.c    4 Jun 2004 13:26:43 -0000
> @@ -882,11 +882,13 @@
>      const char *node = NULL;
>      int            ret;
>  #ifdef ENABLE_THREAD_SAFETY
> +#ifndef WIN32
>      static pthread_once_t check_sigpipe_once = PTHREAD_ONCE_INIT;
>
>      /* Check only on first connection request */
>      pthread_once(&check_sigpipe_once, check_sigpipe_handler);
>  #endif
> +#endif
>
>      if (!conn)
>          return 0;
> @@ -3187,7 +3189,13 @@
>  default_threadlock(int acquire)
>  {
>  #ifdef ENABLE_THREAD_SAFETY
> -    static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
> +    static pthread_mutex_t singlethread_lock;
> +        static int mutex_initialized = 0;
> +        if (!mutex_initialized)
> +        {
> +                mutex_initialized = 1;
> +                pthread_mutex_init(&singlethread_lock, NULL);
> +        }
>      if (acquire)
>          pthread_mutex_lock(&singlethread_lock);
>      else
> Index: fe-secure.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
> retrieving revision 1.41
> diff -u -r1.41 fe-secure.c
> --- fe-secure.c    3 Jun 2004 00:13:19 -0000    1.41
> +++ fe-secure.c    4 Jun 2004 13:26:45 -0000
> @@ -864,8 +864,13 @@
>  init_ssl_system(PGconn *conn)
>  {
>  #ifdef ENABLE_THREAD_SAFETY
> -static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
> -
> +        static pthread_mutex_t init_mutex;
> +        static int mutex_initialized = 0;
> +        if (!mutex_initialized)
> +        {
> +                mutex_initialized = 1;
> +                pthread_mutex_init(&init_mutex, NULL);
> +        }
>      pthread_mutex_lock(&init_mutex);
>
>      if (pq_initssllib && pq_lockarray == NULL) {
> @@ -1171,6 +1176,7 @@
>
>
>  #ifdef ENABLE_THREAD_SAFETY
> +#ifndef WIN32
>  /*
>   *    Check SIGPIPE handler and perhaps install our own.
>   */
> @@ -1210,6 +1216,7 @@
>      if (!PQinSend())
>          exit(128 + SIGPIPE);    /* typical return value for SIG_DFL */
>  }
> +#endif
>  #endif
>
>  /*

> /*-------------------------------------------------------------------------
> *
> * pthread-win32.c
> *    partial pthread implementation for win32
> *
> * Copyright (c) 2004, PostgreSQL Global Development Group
> * IDENTIFICATION
> *   $PostgreSQL: $
> *
> *-------------------------------------------------------------------------
> */
>
>
> #include "windows.h"
> #include "pthread.h"
>
> HANDLE pthread_self()
> {
>    return GetCurrentThread();
> }
>
> void pthread_setspecific(pthread_key_t key, void *val)
> {
> }
>
> void *pthread_getspecific(pthread_key_t key)
> {
>     return NULL;
> }
>
> void pthread_mutex_init(pthread_mutex_t *mp, void *attr)
> {
>    *mp = CreateMutex(0, 0, 0);
> }
>
> void pthread_mutex_lock(pthread_mutex_t *mp)
> {
>    WaitForSingleObject(*mp, INFINITE);
> }
>
> void pthread_mutex_unlock(pthread_mutex_t *mp)
> {
>    ReleaseMutex(*mp);
> }

> #ifndef __PTHREAD_H
> #define __PTHREAD_H
>
> typedef ULONG pthread_key_t;
> typedef HANDLE pthread_mutex_t;
> typedef int pthread_once_t;
>
> HANDLE pthread_self();
>
> void pthread_setspecific(pthread_key_t, void*);
> void* pthread_getspecific(pthread_key_t);
>
> void pthread_mutex_init(pthread_mutex_t *, void *attr);
> void pthread_mutex_lock(pthread_mutex_t*); // blocking
> void pthread_mutex_unlock(pthread_mutex_t*);
>
> #endif

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: delayed planning of unnamed statements
Next
From: Bruce Momjian
Date:
Subject: Re: pgpipe error reporting