Re: [HACKERS] libpq problem - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [HACKERS] libpq problem
Date
Msg-id 200408171653.i7HGrue05863@candle.pha.pa.us
Whole thread Raw
In response to Re: [HACKERS] libpq problem  (Andreas Pflug <pgadmin@pse-consulting.de>)
Responses Re: [HACKERS] libpq problem
List pgsql-patches
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

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: [BUGS] 8.0.0beta1: -lpthread missing
Next
From: Bruce Momjian
Date:
Subject: Re: Allow psql to work against non-tablespace servers (e.g.