OK, I like your idea of chaining on to any existing SIGPIPE handler
rather than just do it if none is installed. I also see your fix for
the uninitialized thread-specific variable.
I added some comments to the patch, renamed the pipeheader variable so
it was pg_* to avoid namespace conflicts, and updated the documentation.
Patch attached and applied.
---------------------------------------------------------------------------
Andreas Pflug wrote:
> Andreas Pflug wrote:
> > Some recent change in libpq seems to interfere with gtk.
> >
> > After I tested a new pgadmin3 version on linuy yesterday, I found that
> > the GUI is hanging after PQconnectdb was called. After the call, the db
> > connection is fully functional, but the GUI mouse will show "waiting"
> > and the program doesn't react to mouse clicks any more; screen updates
> > are not performed either.
> >
> > When I replace the 8.0 libpq.so* version with an older saved version
> > (7.4.3 from debian installation) it works ok.
>
> OK, I found out. Seems I didn't run make distclean for a longer time, so
> I didn't realize earlier.
>
> The reason is the sigpipe handling code. If the app (in this case: some
> gtk internals) already installed a SIGPIPE handler, the thread_in_send
> key is not created. pthread_setspecific calls will thus use an invalid
> key, which screws up gtk.
>
> The attached patch will implement two features:
> 1) unconditionally create thread_in_send
> 2) Always register our own SIGPIPE handler, chain to a previously
> registered handler when the signal is thrown while not sending.
>
> Regards,
> Andreas
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
> joining column's datatypes do not match
--
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
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/libpq.sgml,v
retrieving revision 1.159
diff -c -c -r1.159 libpq.sgml
*** doc/src/sgml/libpq.sgml 16 Aug 2004 02:12:29 -0000 1.159
--- doc/src/sgml/libpq.sgml 17 Aug 2004 16:43:10 -0000
***************
*** 3738,3745 ****
<function>send()</> call and restores the original signal handler after
completion. When <literal>--enable-thread-safety</> is used,
<application>libpq</> installs its own <literal>SIGPIPE</> handler
! before the first database connection if no custom <literal>SIGPIPE</>
! handler has been installed previously. This handler uses thread-local
storage to determine if a <literal>SIGPIPE</> signal has been generated
by a libpq <function>send()</>. If an application wants to install
its own <literal>SIGPIPE</> signal handler, it should call
--- 3738,3744 ----
<function>send()</> call and restores the original signal handler after
completion. When <literal>--enable-thread-safety</> is used,
<application>libpq</> installs its own <literal>SIGPIPE</> handler
! before the first database connection. This handler uses thread-local
storage to determine if a <literal>SIGPIPE</> signal has been generated
by a libpq <function>send()</>. If an application wants to install
its own <literal>SIGPIPE</> signal handler, it should call
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.46
diff -c -c -r1.46 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 17 Aug 2004 04:24:23 -0000 1.46
--- src/interfaces/libpq/fe-secure.c 17 Aug 2004 16:43:19 -0000
***************
*** 152,158 ****
#ifdef ENABLE_THREAD_SAFETY
static void sigpipe_handler_ignore_send(int signo);
! pthread_key_t pq_thread_in_send = 0;
#endif
/* ------------------------------------------------------------ */
--- 152,159 ----
#ifdef ENABLE_THREAD_SAFETY
static void sigpipe_handler_ignore_send(int signo);
! pthread_key_t pq_thread_in_send = 0; /* initializer needed on Darwin */
! static pqsigfunc pq_pipe_handler;
#endif
/* ------------------------------------------------------------ */
***************
*** 1190,1212 ****
void
pq_check_sigpipe_handler(void)
{
! 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(&pq_thread_in_send, NULL);
! pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
! }
}
/*
--- 1191,1202 ----
void
pq_check_sigpipe_handler(void)
{
! pthread_key_create(&pq_thread_in_send, NULL);
/*
! * Find current pipe handler and chain on to it.
*/
! pq_pipe_handler = pqsignalinquire(SIGPIPE);
! pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
}
/*
***************
*** 1216,1227 ****
sigpipe_handler_ignore_send(int signo)
{
/*
! * If we have gotten a SIGPIPE outside send(), exit.
! * Synchronous signals are delivered to the thread
! * that caused the signal.
*/
if (!PQinSend())
! exit(128 + SIGPIPE); /* typical return value for SIG_DFL */
}
#endif
#endif
--- 1206,1223 ----
sigpipe_handler_ignore_send(int signo)
{
/*
! * If we have gotten a SIGPIPE outside send(), chain or
! * exit if we are at the end of the chain.
! * Synchronous signals are delivered to the thread that
! * caused the signal.
*/
if (!PQinSend())
! {
! if (pq_pipe_handler == SIG_DFL) /* not set by application */
! exit(128 + SIGPIPE); /* typical return value for SIG_DFL */
! else
! (*pq_pipe_handler)(signo); /* call original handler */
! }
}
#endif
#endif