Re: [HACKERS] libpq thread safety

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Manfred Spraul <manfred(at)colorfullife(dot)com>
Cc: PostgreSQL-patches <pgsql-patches(at)postgresql(dot)org>
Subject: Re: [HACKERS] libpq thread safety
Date: 2004-03-22 03:49:09
Message-ID: 200403220349.i2M3n9e12658@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches


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
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2004-03-22 04:00:46 Re: pg_autovacuum next steps
Previous Message Gavin Sherry 2004-03-22 03:38:34 Re: pg_autovacuum next steps

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2004-03-22 03:57:33 Re: Another pg_autovacuum patch
Previous Message Bruce Momjian 2004-03-22 03:38:53 Re: change output of \dp