I could not get this patch to compile.  I am getting a failure because
BSD/OS doesn't have pthread_rwlock_wrlock().  I am concerned other
platforms might not have it either.

The compile failure is:

gcc -O2 -fno-strict-aliasing -Wall -Wmissing-prototypes -Wmissing-declarations -O1 
-Wall -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wcast-align -fpic 
-I. -I../../../src/include -I/usr/local/include/readline -I/usr/contrib/include  
-DFRONTEND -DSYSCONFDIR='"/usr/local/pgsql/etc"'  -c -o fe-secure.o fe-secure.c
fe-secure.c:848: syntax error before `*'
fe-secure.c:848: warning: type defaults to `int' in declaration of `pq_lockarray'
fe-secure.c:848: warning: data definition has no type or storage class
fe-secure.c: In function `pq_lockingcallback':
fe-secure.c:853: warning: implicit declaration of function `pthread_rwlock_wrlock'
fe-secure.c:855: warning: implicit declaration of function `pthread_rwlock_unlock'
fe-secure.c: In function `init_ssl_system':
fe-secure.c:875: `pthread_rwlock_t' undeclared (first use in this function)
fe-secure.c:875: (Each undeclared identifier is reported only once
fe-secure.c:875: for each function it appears in.)
fe-secure.c:881: warning: implicit declaration of function `pthread_rwlock_init'
gmake: *** [fe-secure.o] Error 1


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

Manfred Spraul wrote:
> Bruce Momjian wrote:
> 
> >Your patch has been added to the PostgreSQL unapplied patches list at:
> >
> >     http://momjian.postgresql.org/cgi-bin/pgpatches
> >
> >I will try to apply it within the next 48 hours.
> >  
> >
> You are too fast: the patch was a proof of concept, not really tested 
> (actually quite buggy).
> Attached are two patches:
> 
> - ready-sigpipe: check_sigpipe_handler skips pthread_create_key if a 
> signal handler was installed. This is wrong - the key is always required.
> - ready-locking: locking around kerberos and openssl.
> 
> The patches pass the regression tests on i386 linux. Kerberos is 
> untested, ssl only partially tested due to the lack of a test setup.
> I'm still not sure if the new code is the right thing for the openssl 
> initialization: libpq calls SSL_library_init() unconditionally. If the 
> calling app uses ssl, too, this might confuse openssl.
> 
> Could you replace my initial proposal with these two patches?
> 
> Btw, is it intentional that THREAD_SUPPORT is not set in src/template/linux?
> 
> --
>     Manfred

> Index: src/backend/libpq/md5.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/md5.c,v
> retrieving revision 1.22
> diff -c -r1.22 md5.c
> *** src/backend/libpq/md5.c   29 Nov 2003 19:51:49 -0000      1.22
> --- src/backend/libpq/md5.c   14 Mar 2004 10:46:54 -0000
> ***************
> *** 271,277 ****
>   static void
>   bytesToHex(uint8 b[16], char *s)
>   {
> !     static char *hex = "0123456789abcdef";
>       int                     q,
>                               w;
>   
> --- 271,277 ----
>   static void
>   bytesToHex(uint8 b[16], char *s)
>   {
> !     static const char *hex = "0123456789abcdef";
>       int                     q,
>                               w;
>   
> Index: src/interfaces/libpq/fe-auth.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-auth.c,v
> retrieving revision 1.89
> diff -c -r1.89 fe-auth.c
> *** src/interfaces/libpq/fe-auth.c    7 Jan 2004 18:56:29 -0000       1.89
> --- src/interfaces/libpq/fe-auth.c    14 Mar 2004 10:46:55 -0000
> ***************
> *** 590,595 ****
> --- 590,596 ----
>   
>               case AUTH_REQ_KRB4:
>   #ifdef KRB4
> +                     pglock_thread();
>                       if (pg_krb4_sendauth(PQerrormsg, conn->sock,
>                                                          (struct sockaddr_in *) & 
> conn->laddr.addr,
>                                                          (struct sockaddr_in *) & 
> conn->raddr.addr,
> ***************
> *** 597,604 ****
> --- 598,607 ----
>                       {
>                               snprintf(PQerrormsg, PQERRORMSG_LENGTH,
>                                       libpq_gettext("Kerberos 4 authentication 
> failed\n"));
> +                             pgunlock_thread();
>                               return STATUS_ERROR;
>                       }
> +                     pgunlock_thread();
>                       break;
>   #else
>                       snprintf(PQerrormsg, PQERRORMSG_LENGTH,
> ***************
> *** 608,620 ****
> --- 611,626 ----
>   
>               case AUTH_REQ_KRB5:
>   #ifdef KRB5
> +                     pglock_thread();
>                       if (pg_krb5_sendauth(PQerrormsg, conn->sock,
>                                                                hostname) != 
> STATUS_OK)
>                       {
>                               snprintf(PQerrormsg, PQERRORMSG_LENGTH,
>                                       libpq_gettext("Kerberos 5 authentication 
> failed\n"));
> +                             pgunlock_thread();
>                               return STATUS_ERROR;
>                       }
> +                     pgunlock_thread();
>                       break;
>   #else
>                       snprintf(PQerrormsg, PQERRORMSG_LENGTH,
> ***************
> *** 722,727 ****
> --- 728,734 ----
>       if (authsvc == 0)
>               return NULL;                    /* leave original error message in 
> place */
>   
> +     pglock_thread();
>   #ifdef KRB4
>       if (authsvc == STARTUP_KRB4_MSG)
>               name = pg_krb4_authname(PQerrormsg);
> ***************
> *** 759,763 ****
> --- 766,771 ----
>   
>       if (name && (authn = (char *) malloc(strlen(name) + 1)))
>               strcpy(authn, name);
> +     pgunlock_thread();
>       return authn;
>   }
> Index: src/interfaces/libpq/fe-connect.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
> retrieving revision 1.268
> diff -c -r1.268 fe-connect.c
> *** src/interfaces/libpq/fe-connect.c 10 Mar 2004 21:12:47 -0000      1.268
> --- src/interfaces/libpq/fe-connect.c 14 Mar 2004 10:46:56 -0000
> ***************
> *** 2902,2908 ****
>   PQsetClientEncoding(PGconn *conn, const char *encoding)
>   {
>       char            qbuf[128];
> !     static char query[] = "set client_encoding to '%s'";
>       PGresult   *res;
>       int                     status;
>   
> --- 2902,2908 ----
>   PQsetClientEncoding(PGconn *conn, const char *encoding)
>   {
>       char            qbuf[128];
> !     static const char query[] = "set client_encoding to '%s'";
>       PGresult   *res;
>       int                     status;
>   
> ***************
> *** 3162,3166 ****
> --- 3162,3207 ----
>       return NULL;
>   
>   #undef LINELEN
> + }
> + 
> + /*
> +  * To keep the API consistent, the locking stubs are always provided, even
> +  * if they are not required.
> +  */
> + 
> + void
> + PQenableSSLLocks(int enable)
> + {
> + #if defined(ENABLE_THREAD_SAFETY) && defined(USE_SSL)
> +     pq_usessllocks = enable;
> + #endif
> + }
> + 
> + static pgthreadlock_t default_threadlock;
> + static void
> + default_threadlock(int acquire)
> + {
> + #if defined(ENABLE_THREAD_SAFETY)
> +     static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
> +     if (acquire)
> +             pthread_mutex_lock(&singlethread_lock);
> +     else
> +             pthread_mutex_unlock(&singlethread_lock);
> + #endif
> + }
> + 
> + pgthreadlock_t *g_threadlock = default_threadlock;
> + 
> + pgthreadlock_t *
> + PQregisterThreadLock(pgthreadlock_t *newhandler)
> + {
> +     pgthreadlock_t *prev;
> + 
> +     prev = g_threadlock;
> +     if (newhandler)
> +             g_threadlock = newhandler;
> +     else
> +             g_threadlock = default_threadlock;
> +     return prev;
>   }
>   
> Index: src/interfaces/libpq/fe-secure.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
> retrieving revision 1.37
> diff -c -r1.37 fe-secure.c
> *** src/interfaces/libpq/fe-secure.c  10 Feb 2004 15:21:24 -0000      1.37
> --- src/interfaces/libpq/fe-secure.c  14 Mar 2004 10:46:56 -0000
> ***************
> *** 135,145 ****
>   static DH  *load_dh_buffer(const char *, size_t);
>   static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
>   static int  client_cert_cb(SSL *, X509 **, EVP_PKEY **);
>   static int  initialize_SSL(PGconn *);
>   static void destroy_SSL(void);
>   static PostgresPollingStatusType open_client_SSL(PGconn *);
>   static void close_SSL(PGconn *);
> ! static const char *SSLerrmessage(void);
>   #endif
>   
>   #ifdef USE_SSL
> --- 135,147 ----
>   static DH  *load_dh_buffer(const char *, size_t);
>   static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
>   static int  client_cert_cb(SSL *, X509 **, EVP_PKEY **);
> + static int  init_ssl_system(PGconn *conn);
>   static int  initialize_SSL(PGconn *);
>   static void destroy_SSL(void);
>   static PostgresPollingStatusType open_client_SSL(PGconn *);
>   static void close_SSL(PGconn *);
> ! static char *SSLerrmessage(void);
> ! static void SSLerrfree(char *buf);
>   #endif
>   
>   #ifdef USE_SSL
> ***************
> *** 251,259 ****
>                       !SSL_set_app_data(conn->ssl, conn) ||
>                       !SSL_set_fd(conn->ssl, conn->sock))
>               {
>                       printfPQExpBuffer(&conn->errorMessage,
>                          libpq_gettext("could not establish SSL connection: %s\n"),
> !                                                       SSLerrmessage());
>                       close_SSL(conn);
>                       return PGRES_POLLING_FAILED;
>               }
> --- 253,263 ----
>                       !SSL_set_app_data(conn->ssl, conn) ||
>                       !SSL_set_fd(conn->ssl, conn->sock))
>               {
> +                     char *err = SSLerrmessage();
>                       printfPQExpBuffer(&conn->errorMessage,
>                          libpq_gettext("could not establish SSL connection: %s\n"),
> !                                                       err);
> !                     SSLerrfree(err);
>                       close_SSL(conn);
>                       return PGRES_POLLING_FAILED;
>               }
> ***************
> *** 327,334 ****
>                                       break;
>                               }
>                       case SSL_ERROR_SSL:
> !                             printfPQExpBuffer(&conn->errorMessage,
> !                                       libpq_gettext("SSL error: %s\n"), 
> SSLerrmessage());
>                               /* fall through */
>                       case SSL_ERROR_ZERO_RETURN:
>                               SOCK_ERRNO_SET(ECONNRESET);
> --- 331,342 ----
>                                       break;
>                               }
>                       case SSL_ERROR_SSL:
> !                             {
> !                                     char *err = SSLerrmessage();
> !                                     printfPQExpBuffer(&conn->errorMessage,
> !                                               libpq_gettext("SSL error: %s\n"), 
> err);
> !                                     SSLerrfree(err);
> !                             }
>                               /* fall through */
>                       case SSL_ERROR_ZERO_RETURN:
>                               SOCK_ERRNO_SET(ECONNRESET);
> ***************
> *** 402,409 ****
>                                       break;
>                               }
>                       case SSL_ERROR_SSL:
> !                             printfPQExpBuffer(&conn->errorMessage,
> !                                       libpq_gettext("SSL error: %s\n"), 
> SSLerrmessage());
>                               /* fall through */
>                       case SSL_ERROR_ZERO_RETURN:
>                               SOCK_ERRNO_SET(ECONNRESET);
> --- 410,421 ----
>                                       break;
>                               }
>                       case SSL_ERROR_SSL:
> !                             {
> !                                     char *err = SSLerrmessage();
> !                                     printfPQExpBuffer(&conn->errorMessage,
> !                                               libpq_gettext("SSL error: %s\n"), 
> err);
> !                                     SSLerrfree(err);
> !                             }
>                               /* fall through */
>                       case SSL_ERROR_ZERO_RETURN:
>                               SOCK_ERRNO_SET(ECONNRESET);
> ***************
> *** 750,758 ****
>       }
>       if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
>       {
>               printfPQExpBuffer(&conn->errorMessage,
>                                 libpq_gettext("could not read certificate (%s): 
> %s\n"),
> !                                               fnbuf, SSLerrmessage());
>               fclose(fp);
>               return -1;
>       }
> --- 762,772 ----
>       }
>       if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
>       {
> +             char *err = SSLerrmessage();
>               printfPQExpBuffer(&conn->errorMessage,
>                                 libpq_gettext("could not read certificate (%s): 
> %s\n"),
> !                                               fnbuf, err);
> !             SSLerrfree(err);
>               fclose(fp);
>               return -1;
>       }
> ***************
> *** 795,803 ****
>       }
>       if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
>       {
>               printfPQExpBuffer(&conn->errorMessage,
>                                 libpq_gettext("could not read private key (%s): 
> %s\n"),
> !                                               fnbuf, SSLerrmessage());
>               X509_free(*x509);
>               fclose(fp);
>               return -1;
> --- 809,819 ----
>       }
>       if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
>       {
> +             char *err = SSLerrmessage();
>               printfPQExpBuffer(&conn->errorMessage,
>                                 libpq_gettext("could not read private key (%s): 
> %s\n"),
> !                                               fnbuf, err);
> !             SSLerrfree(err);
>               X509_free(*x509);
>               fclose(fp);
>               return -1;
> ***************
> *** 807,815 ****
>       /* verify that the cert and key go together */
>       if (!X509_check_private_key(*x509, *pkey))
>       {
>               printfPQExpBuffer(&conn->errorMessage,
>                       libpq_gettext("certificate/private key mismatch (%s): %s\n"),
> !                                               fnbuf, SSLerrmessage());
>               X509_free(*x509);
>               EVP_PKEY_free(*pkey);
>               return -1;
> --- 823,833 ----
>       /* verify that the cert and key go together */
>       if (!X509_check_private_key(*x509, *pkey))
>       {
> +             char *err = SSLerrmessage();
>               printfPQExpBuffer(&conn->errorMessage,
>                       libpq_gettext("certificate/private key mismatch (%s): %s\n"),
> !                                               fnbuf, err);
> !             SSLerrfree(err);
>               X509_free(*x509);
>               EVP_PKEY_free(*pkey);
>               return -1;
> ***************
> *** 819,838 ****
>   #endif
>   }
>   
> ! /*
> !  *  Initialize global SSL context.
> !  */
>   static int
> ! initialize_SSL(PGconn *conn)
>   {
> ! #ifndef WIN32
> !     struct stat buf;
> !     char            pwdbuf[BUFSIZ];
> !     struct passwd pwdstr;
> !     struct passwd *pwd = NULL;
> !     char            fnbuf[2048];
> ! #endif
>   
>       if (!SSL_context)
>       {
>               SSL_library_init();
> --- 837,888 ----
>   #endif
>   }
>   
> ! #ifdef ENABLE_THREAD_SAFETY
> ! 
> ! static unsigned long
> ! pq_threadidcallback(void)
> ! {
> !     return (unsigned long)pthread_self();
> ! }
> ! 
> ! static pthread_rwlock_t *pq_lockarray;
> ! static void
> ! pq_lockingcallback(int mode, int n, const char *file, int line)
> ! {
> !     if (mode & CRYPTO_LOCK) {
> !             pthread_rwlock_wrlock(&pq_lockarray[n]);
> !     } else {
> !             pthread_rwlock_unlock(&pq_lockarray[n]);
> !     }
> ! }
> ! 
> ! bool pq_usessllocks = true;
> ! 
> ! #endif /* ENABLE_THRAD_SAFETY */
> ! 
>   static int
> ! init_ssl_system(PGconn *conn)
>   {
> ! #ifdef ENABLE_THREAD_SAFETY
> ! static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
> ! 
> !     pthread_mutex_lock(&init_mutex);
> !     
> !     if (pq_usessllocks && pq_lockarray == NULL) {
> !             int i;
> !             CRYPTO_set_id_callback(pq_threadidcallback);
> ! 
> !             pq_lockarray = malloc(sizeof(pthread_rwlock_t)*CRYPTO_num_locks());
> !             if (!pq_lockarray) {
> !                     pthread_mutex_unlock(&init_mutex);
> !                     return -1;
> !             }
> !             for (i=0;i<CRYPTO_num_locks();i++)
> !                     pthread_rwlock_init(&pq_lockarray[i], NULL);
>   
> +             CRYPTO_set_locking_callback(pq_lockingcallback);
> +     }
> + #endif
>       if (!SSL_context)
>       {
>               SSL_library_init();
> ***************
> *** 840,851 ****
>               SSL_context = SSL_CTX_new(TLSv1_method());
>               if (!SSL_context)
>               {
>                       printfPQExpBuffer(&conn->errorMessage,
>                                        libpq_gettext("could not create SSL context: 
> %s\n"),
> !                                                       SSLerrmessage());
>                       return -1;
>               }
>       }
>   
>   #ifndef WIN32
>       if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)
> --- 890,927 ----
>               SSL_context = SSL_CTX_new(TLSv1_method());
>               if (!SSL_context)
>               {
> +                     char *err = SSLerrmessage();
>                       printfPQExpBuffer(&conn->errorMessage,
>                                        libpq_gettext("could not create SSL context: 
> %s\n"),
> !                                                       err);
> !                     SSLerrfree(err);
> ! #ifdef ENABLE_THREAD_SAFETY
> !                     pthread_mutex_unlock(&init_mutex);
> ! #endif
>                       return -1;
>               }
>       }
> + #ifdef ENABLE_THREAD_SAFETY
> +     pthread_mutex_unlock(&init_mutex);
> + #endif
> +     return 0;
> + }
> + /*
> +  *  Initialize global SSL context.
> +  */
> + static int
> + initialize_SSL(PGconn *conn)
> + {
> + #ifndef WIN32
> +     struct stat buf;
> +     char            pwdbuf[BUFSIZ];
> +     struct passwd pwdstr;
> +     struct passwd *pwd = NULL;
> +     char            fnbuf[2048];
> + #endif
> + 
> +     if(!init_ssl_system(conn))
> +             return -1;
>   
>   #ifndef WIN32
>       if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)
> ***************
> *** 867,875 ****
>               }
>               if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))
>               {
>                       printfPQExpBuffer(&conn->errorMessage,
>                                                         libpq_gettext("could not 
> read root certificate list (%s): %s\n"),
> !                                                       fnbuf, SSLerrmessage());
>                       return -1;
>               }
>       }
> --- 943,953 ----
>               }
>               if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))
>               {
> +                     char *err = SSLerrmessage();
>                       printfPQExpBuffer(&conn->errorMessage,
>                                                         libpq_gettext("could not 
> read root certificate list (%s): %s\n"),
> !                                                       fnbuf, err);
> !                     SSLerrfree(err);
>                       return -1;
>               }
>       }
> ***************
> *** 936,945 ****
>                                       return PGRES_POLLING_FAILED;
>                               }
>                       case SSL_ERROR_SSL:
> !                             printfPQExpBuffer(&conn->errorMessage,
> !                                       libpq_gettext("SSL error: %s\n"), 
> SSLerrmessage());
> !                             close_SSL(conn);
> !                             return PGRES_POLLING_FAILED;
>   
>                       default:
>                               printfPQExpBuffer(&conn->errorMessage,
> --- 1014,1027 ----
>                                       return PGRES_POLLING_FAILED;
>                               }
>                       case SSL_ERROR_SSL:
> !                             {
> !                                     char *err = SSLerrmessage();
> !                                     printfPQExpBuffer(&conn->errorMessage,
> !                                               libpq_gettext("SSL error: %s\n"), 
> err);
> !                                     SSLerrfree(err);
> !                                     close_SSL(conn);
> !                                     return PGRES_POLLING_FAILED;
> !                             }
>   
>                       default:
>                               printfPQExpBuffer(&conn->errorMessage,
> ***************
> *** 973,981 ****
>       conn->peer = SSL_get_peer_certificate(conn->ssl);
>       if (conn->peer == NULL)
>       {
>               printfPQExpBuffer(&conn->errorMessage,
>                               libpq_gettext("certificate could not be obtained: 
> %s\n"),
> !                                               SSLerrmessage());
>               close_SSL(conn);
>               return PGRES_POLLING_FAILED;
>       }
> --- 1055,1065 ----
>       conn->peer = SSL_get_peer_certificate(conn->ssl);
>       if (conn->peer == NULL)
>       {
> +             char *err = SSLerrmessage();
>               printfPQExpBuffer(&conn->errorMessage,
>                               libpq_gettext("certificate could not be obtained: 
> %s\n"),
> !                                               err);
> !             SSLerrfree(err);
>               close_SSL(conn);
>               return PGRES_POLLING_FAILED;
>       }
> ***************
> *** 1036,1058 ****
>    * return NULL if it doesn't recognize the error code.  We don't
>    * want to return NULL ever.
>    */
> ! static const char *
>   SSLerrmessage(void)
>   {
>       unsigned long errcode;
>       const char *errreason;
> !     static char errbuf[32];
>   
>       errcode = ERR_get_error();
> !     if (errcode == 0)
> !             return "No SSL error reported";
>       errreason = ERR_reason_error_string(errcode);
> !     if (errreason != NULL)
> !             return errreason;
> !     snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);
>       return errbuf;
>   }
>   
>   /*
>    *  Return pointer to SSL object.
>    */
> --- 1120,1159 ----
>    * return NULL if it doesn't recognize the error code.  We don't
>    * want to return NULL ever.
>    */
> ! static char ssl_nomem[] = "Out of memory allocating error description";
> ! #define SSL_ERR_LEN 128
> ! 
> ! static char *
>   SSLerrmessage(void)
>   {
>       unsigned long errcode;
>       const char *errreason;
> !     char *errbuf;
>   
> +     errbuf = malloc(SSL_ERR_LEN);
> +     if (!errbuf)
> +             return ssl_nomem;
>       errcode = ERR_get_error();
> !     if (errcode == 0) {
> !             strcpy(errbuf, "No SSL error reported");
> !             return errbuf;
> !     }
>       errreason = ERR_reason_error_string(errcode);
> !     if (errreason != NULL) {
> !             strncpy(errbuf, errreason, SSL_ERR_LEN-1);
> !             errbuf[SSL_ERR_LEN-1] = '\0';
> !             return errbuf;
> !     }
> !     snprintf(errbuf, SSL_ERR_LEN, "SSL error code %lu", errcode);
>       return errbuf;
>   }
>   
> + static void
> + SSLerrfree(char *buf)
> + {
> +     if (buf != ssl_nomem)
> +             free(buf);
> + }
>   /*
>    *  Return pointer to SSL object.
>    */
> Index: src/interfaces/libpq/libpq-fe.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-fe.h,v
> retrieving revision 1.102
> diff -c -r1.102 libpq-fe.h
> *** src/interfaces/libpq/libpq-fe.h   9 Jan 2004 02:02:43 -0000       1.102
> --- src/interfaces/libpq/libpq-fe.h   14 Mar 2004 10:46:57 -0000
> ***************
> *** 274,279 ****
> --- 274,293 ----
>                                        PQnoticeProcessor proc,
>                                        void *arg);
>   
> + /*
> +  *     Used to set callback that prevents concurrent access to
> +  *     non-thread safe functions that libpq needs.
> +  *     The default implementation uses a libpq internal mutex.
> +  *     Only required for multithreaded apps that use kerberos
> +  *     both within their app and for postgresql connections.
> +  */
> + typedef void (pgthreadlock_t)(int acquire);
> + 
> + extern pgthreadlock_t * PQregisterThreadLock(pgthreadlock_t *newhandler);
> + 
> + void
> + PQenableSSLLocks(int enable);
> + 
>   /* === in fe-exec.c === */
>   
>   /* Simple synchronous query */
> Index: src/interfaces/libpq/libpq-int.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
> retrieving revision 1.85
> diff -c -r1.85 libpq-int.h
> *** src/interfaces/libpq/libpq-int.h  5 Mar 2004 01:53:59 -0000       1.85
> --- src/interfaces/libpq/libpq-int.h  14 Mar 2004 10:46:57 -0000
> ***************
> *** 359,364 ****
> --- 359,374 ----
>   extern int pqPacketSend(PGconn *conn, char pack_type,
>                        const void *buf, size_t buf_len);
>   
> + #ifdef ENABLE_THREAD_SAFETY
> + extern pgthreadlock_t *g_threadlock;
> + #define pglock_thread() g_threadlock(true);
> + #define pgunlock_thread() g_threadlock(false);
> + #else
> + #define pglock_thread() ((void)0)
> + #define pgunlock_thread() ((void)0)
> + #endif
> +      
> + 
>   /* === in fe-exec.c === */
>   
>   extern void pqSetResultError(PGresult *res, const char *msg);
> ***************
> *** 448,453 ****
> --- 458,464 ----
>   #ifdef ENABLE_THREAD_SAFETY
>   extern void check_sigpipe_handler(void);
>   extern pthread_key_t thread_in_send;
> + extern bool pq_usessllocks;
>   #endif
>   
>   /*

> Index: src/interfaces/libpq/fe-secure.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
> retrieving revision 1.37
> diff -c -r1.37 fe-secure.c
> *** src/interfaces/libpq/fe-secure.c  10 Feb 2004 15:21:24 -0000      1.37
> --- src/interfaces/libpq/fe-secure.c  14 Mar 2004 08:31:48 -0000
> ***************
> *** 1077,1096 ****
>       pqsigfunc pipehandler;
>   
>       /*
>        *      If the app hasn't set a SIGPIPE handler, define our own
>        *      that ignores SIGPIPE on libpq send() and does SIG_DFL
>        *      for other SIGPIPE cases.
>        */
>       pipehandler = pqsignalinquire(SIGPIPE);
>       if (pipehandler == SIG_DFL)     /* not set by application */
> -     {
> -             /*
> -              *      Create key first because the signal handler might be called
> -              *      right after being installed.
> -              */
> -             pthread_key_create(&thread_in_send, NULL);      
>               pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
> -     }
>   }
>   
>   /*
> --- 1077,1096 ----
>       pqsigfunc pipehandler;
>   
>       /*
> +      *      Always create the key for SIGPIPE handling - PQinSend needs
> +      *      it. Create it first because the signal handler might be called
> +      *      right after being installed.
> +      */
> +     pthread_key_create(&thread_in_send, NULL);      
> + 
> +     /*
>        *      If the app hasn't set a SIGPIPE handler, define our own
>        *      that ignores SIGPIPE on libpq send() and does SIG_DFL
>        *      for other SIGPIPE cases.
>        */
>       pipehandler = pqsignalinquire(SIGPIPE);
>       if (pipehandler == SIG_DFL)     /* not set by application */
>               pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
>   }
>   
>   /*

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
> 
>                http://www.postgresql.org/docs/faqs/FAQ.html

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

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to