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.

Regards,
Andreas

Wed, 11 Aug 2004 13:07:09 +0000
Andreas Pflug <pgadmin@pse-consulting.de>
libpq problem
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
Wed, 11 Aug 2004 14:58:49 +0000
Andreas Pflug <pgadmin@pse-consulting.de>
Re: libpq problem
Am Mittwoch, 11. August 2004 15:07 schrieb Andreas Pflug:
> Some recent change in libpq seems to interfere with gtk.

You could use "nm" to find common symbols that might be clashing.  Besides 
that, it's hard to tell more.  Alternatively, compile with versioned symbols 
and see whether the problem goes away.

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/

Wed, 11 Aug 2004 19:05:10 +0200
Peter Eisentraut <peter_e@gmx.net>
Re: libpq problem
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
Tue, 17 Aug 2004 12:53:56 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: [HACKERS] libpq problem
Bruce Momjian wrote:
> 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.

At a glance, this looks like it will break applications that pass 
SA_SIGINFO in sa_flags for their SIGPIPE handlers. This changes the 
expected signal handler signature to a three-arg form; the extra two 
args provide context about where the signal occurred. The libpq handler, 
however, doesn't pass those args when chaining to the next handler.

The Sun JVM under linux is one example of an app that does1 this. I've 
seen a similar problem to this before with a version of libnss_ldap that 
did not correctly restore the entire sigaction state when restoring the 
SIGPIPE handler before returning from libnss_ldap .. the next SIGPIPE 
that arrives would crash the JVM. See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4630104 for more 
details (requires registration)

-O

Wed, 18 Aug 2004 11:43:21 +1200
Oliver Jowett <oliver@opencloud.com>
Re: [HACKERS] libpq problem