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
  [EMAIL PROTECTED]               |  (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
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])

Reply via email to