<div dir="ltr">Hi Tatsuo<div><br><div>I have been trying to reproduce this compilation issue but unable to do so. I have compiled the patched code with GCC 4.6.3 and also with </div><div>LLVM 5.0 and in both case I am able to successfully compile the code. </div>
<div>Can you please guide me to reproduce the issue at my end as the Oid definition which is conflicting at your end is not changed by the patch.</div><div><br></div><div><div>here is the gcc log of files compilation, </div>
</div><div><br></div><div><div><span class="" style="white-space:pre">        </span>gcc -DHAVE_CONFIG_H -DDEFAULT_CONFIGDIR=\&quot;/home/usama/EDB/pgpool/elog_work/mypgpool/test/comanddel/installed/etc\&quot; -I. -I../src/include  -D_GNU_SOURCE -I /home/usama/EDB/PG/installed/include   -O0 -g3 -Wall -Wmissing-prototypes -Wmissing-declarations -MT main/main.o -MD -MP -MF $depbase.Tpo -c -o main/main.o main/main.c &amp;&amp;\</div>
<div><span class="" style="white-space:pre">        </span>mv -f $depbase.Tpo $depbase.Po</div><div>main/main.c: In function ‘daemonize’:</div><div>main/main.c:384:17: warning: variable ‘rc_chdir’ set but not used [-Wunused-but-set-variable]</div>
<div>depbase=`echo main/pgpool_main.o | sed &#39;s|[^/]*$|.deps/&amp;|;s|\.o$||&#39;`;\</div><div><span class="" style="white-space:pre">        </span>gcc -DHAVE_CONFIG_H -DDEFAULT_CONFIGDIR=\&quot;/home/usama/EDB/pgpool/elog_work/mypgpool/test/comanddel/installed/etc\&quot; -I. -I../src/include  -D_GNU_SOURCE -I /home/usama/EDB/PG/installed/include   -O0 -g3 -Wall -Wmissing-prototypes -Wmissing-declarations -MT main/pgpool_main.o -MD -MP -MF $depbase.Tpo -c -o main/pgpool_main.o main/pgpool_main.c &amp;&amp;\</div>
<div><span class="" style="white-space:pre">        </span>mv -f $depbase.Tpo $depbase.Po</div><div>main/pgpool_main.c: In function ‘find_primary_node’:</div><div>main/pgpool_main.c:1981:14: warning: variable ‘status’ set but not used [-Wunused-but-set-variable]</div>
</div><div>..</div><div><br></div><div>pgpool2$ gcc --version<br></div><div><div>gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3</div><div>Copyright (C) 2011 Free Software Foundation, Inc.</div><div><br></div><div>And on OS/X the compilation is also successfull. </div>
<div><div>gcc --version</div><div>Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1</div><div>Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)</div>
<div>Target: x86_64-apple-darwin12.5.0</div></div><div><br></div><div>Thanks</div><div>Usama</div><div><br></div></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Oct 12, 2013 at 5:41 AM, Tatsuo Ishii <span dir="ltr">&lt;<a href="mailto:ishii@postgresql.org" target="_blank">ishii@postgresql.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I have freshly checkout git master and applied your patch.<br>
I got this:<br>
<br>
        gcc -DHAVE_CONFIG_H -DDEFAULT_CONFIGDIR=\&quot;/home/t-ishii/work/<a href="http://git.postgresql.org/exception/pgpool2/src/test/regression/temp/installed/etc\" target="_blank">git.postgresql.org/exception/pgpool2/src/test/regression/temp/installed/etc\</a>&quot; -I. -I../src/include  -D_GNU_SOURCE -I /usr/local/pgsql/include   -g -O2 -Wall -Wmissing-prototypes -Wmissing-declarations -MT main/pgpool_main.o -MD -MP -MF $depbase.Tpo -c -o main/pgpool_main.o main/pgpool_main.c &amp;&amp;\<br>

        mv -f $depbase.Tpo $depbase.Po<br>
In file included from /usr/local/pgsql/include/libpq-fe.h:29,<br>
                 from ../src/include/pool.h:34,<br>
                 from main/pgpool_main.c:51:<br>
/usr/local/pgsql/include/postgres_ext.h:31: error: redefinition of typedef ‘PoolOid’<br>
../src/include/parser/pool_parser.h:43: note: previous declaration of ‘PoolOid’ was here<br>
<br>
This is caused by the conflict in postgres_ext.h:<br>
typedef unsigned int Oid;<br>
<br>
and<br>
<br>
./include/parser/pool_parser.h:typedef unsigned int PoolOid;<br>
./include/parser/pool_parser.h:#define Oid PoolOid<br>
<br>
This is gcc 4.4.5.<br>
<div class="HOEnZb"><div class="h5">--<br>
Tatsuo Ishii<br>
SRA OSS, Inc. Japan<br>
English: <a href="http://www.sraoss.co.jp/index_en.php" target="_blank">http://www.sraoss.co.jp/index_en.php</a><br>
Japanese: <a href="http://www.sraoss.co.jp" target="_blank">http://www.sraoss.co.jp</a><br>
<br>
&gt; Hi<br>
&gt;<br>
&gt; Seems like the repository was changed after I had generated the patch.<br>
&gt; Please find the updated patch rebased with the current state of git.<br>
&gt;<br>
&gt;<br>
&gt; Thanks<br>
&gt; Usama<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Fri, Oct 11, 2013 at 9:47 AM, Ahsan Hadi &lt;<a href="mailto:ahsan.hadi@enterprisedb.com">ahsan.hadi@enterprisedb.com</a>&gt;wrote:<br>
&gt;<br>
&gt;&gt; Usama,<br>
&gt;&gt; Please take a look.<br>
&gt;&gt;<br>
&gt;&gt; Tatsuo,<br>
&gt;&gt; I was apply to apply this patch cleanly on pgpool master and test before<br>
&gt;&gt; Usama sent the patch. It is likely that we have done some changes to the<br>
&gt;&gt; master branch since then..<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Fri, Oct 11, 2013 at 4:03 AM, Tatsuo Ishii &lt;<a href="mailto:ishii@postgresql.org">ishii@postgresql.org</a>&gt;wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt; Usama,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I have applied your patch and got following error:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Hunk #12 FAILED at 499.<br>
&gt;&gt;&gt; 1 out of 12 hunks FAILED -- saving rejects to file src/main/main.c.rej<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I also attached main.c.rej.<br>
&gt;&gt;&gt; --<br>
&gt;&gt;&gt; Tatsuo Ishii<br>
&gt;&gt;&gt; SRA OSS, Inc. Japan<br>
&gt;&gt;&gt; English: <a href="http://www.sraoss.co.jp/index_en.php" target="_blank">http://www.sraoss.co.jp/index_en.php</a><br>
&gt;&gt;&gt; Japanese: <a href="http://www.sraoss.co.jp" target="_blank">http://www.sraoss.co.jp</a><br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; Muhammad,<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Thank you for your great work! I&#39;ll look into this.<br>
&gt;&gt;&gt; &gt; --<br>
&gt;&gt;&gt; &gt; Tatsuo Ishii<br>
&gt;&gt;&gt; &gt; SRA OSS, Inc. Japan<br>
&gt;&gt;&gt; &gt; English: <a href="http://www.sraoss.co.jp/index_en.php" target="_blank">http://www.sraoss.co.jp/index_en.php</a><br>
&gt;&gt;&gt; &gt; Japanese: <a href="http://www.sraoss.co.jp" target="_blank">http://www.sraoss.co.jp</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; Hi<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; I am working on adding the exception manager in pgpool and my plan of<br>
&gt;&gt;&gt; &gt;&gt; action for this is to use the Postgres exception manager API (elog and<br>
&gt;&gt;&gt; &gt;&gt; friends). Since the exception manager in Postgres uses the long jump,<br>
&gt;&gt;&gt; so<br>
&gt;&gt;&gt; &gt;&gt; importing this API in pgpool will effect all existing pgpool code flows<br>
&gt;&gt;&gt; &gt;&gt; especially in case of an error. and lot of care will be required for<br>
&gt;&gt;&gt; this<br>
&gt;&gt;&gt; &gt;&gt; integration, and secondly the elog API along with its friends will<br>
&gt;&gt;&gt; touch<br>
&gt;&gt;&gt; &gt;&gt; almost all parts of pgpool source code which will add up to a very huge<br>
&gt;&gt;&gt; &gt;&gt; patch.<br>
&gt;&gt;&gt; &gt;&gt; So instead throwing a very huge patch to the community my plan is to<br>
&gt;&gt;&gt; divide<br>
&gt;&gt;&gt; &gt;&gt; this task into multiple smaller sub tasks so that it would be easier<br>
&gt;&gt;&gt; &gt;&gt; maintain and review the patch.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; Cut to the chase, attached is the  first of the series of related<br>
&gt;&gt;&gt; patches<br>
&gt;&gt;&gt; &gt;&gt; to come.This is the first cut patch for implementing the exception<br>
&gt;&gt;&gt; manager<br>
&gt;&gt;&gt; &gt;&gt; in pgpool. As described above the exception manager and related code is<br>
&gt;&gt;&gt; &gt;&gt; borrowed from PostgreSQL source code.<br>
&gt;&gt;&gt; &gt;&gt; and the exception manager (elog API) is very closely tied with memory<br>
&gt;&gt;&gt; &gt;&gt; manager in PostgreSQL (palloc API) so the patch also borrows the PG&#39;s<br>
&gt;&gt;&gt; &gt;&gt; memory manager.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; Below is the little description of things part of this patch.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- Exception manager API of Postgres is added to pgpool, The API<br>
&gt;&gt;&gt; consists<br>
&gt;&gt;&gt; &gt;&gt; of elog.c and elog.h files. Since this API is very extensive and is<br>
&gt;&gt;&gt; &gt;&gt; designed for PostgreSQL so to fit it properly into pgpool I have<br>
&gt;&gt;&gt; modified<br>
&gt;&gt;&gt; &gt;&gt; it a little bit, and most of the modifications are related to removal<br>
&gt;&gt;&gt; of<br>
&gt;&gt;&gt; &gt;&gt; code which is not required for pgpool.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- Added on_proc_exit callback mechanism of Postgres. To facilitate the<br>
&gt;&gt;&gt; &gt;&gt; cleanup at exit time.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- Added PostgreSQL&#39;s memory manager (palloc API). This includes the<br>
&gt;&gt;&gt; client<br>
&gt;&gt;&gt; &gt;&gt; side palloc functions placed in &#39;src/tools&#39; directory (fe_memutils)<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- Removed the existing memory manager which was very minimalistic and<br>
&gt;&gt;&gt; was<br>
&gt;&gt;&gt; &gt;&gt; not integrated in all parts of the code.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- I have also tried to reflector some portions of code to make the<br>
&gt;&gt;&gt; code<br>
&gt;&gt;&gt; &gt;&gt; more readable at first glance. This includes<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; - dividing the main.c file into two files main.c and pgpool_main.c,<br>
&gt;&gt;&gt; Now the<br>
&gt;&gt;&gt; &gt;&gt; main.c file only contains the code related to early initialisations of<br>
&gt;&gt;&gt; &gt;&gt; pgpool and parsing the command line options and related code. The<br>
&gt;&gt;&gt; actual<br>
&gt;&gt;&gt; &gt;&gt; logic of the pgpool main process is moved to new pgpool_main.c file.<br>
&gt;&gt;&gt; &gt;&gt; - breaking up some large functions in child.c into smaller functions.<br>
&gt;&gt;&gt; &gt;&gt; - rewrite the pgpool&#39;s main loop logic to make the code more readable.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; Remaining TODOs on this front.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- The current patch only integrates the memory and exception manager<br>
&gt;&gt;&gt; in<br>
&gt;&gt;&gt; &gt;&gt; main process and connection creation segment of pgpool child process.<br>
&gt;&gt;&gt; &gt;&gt; integration of newly added APIs in pcp and worker child process codes<br>
&gt;&gt;&gt; will<br>
&gt;&gt;&gt; &gt;&gt; be done be next patch.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- Integration of newly added API into query processor logic in child<br>
&gt;&gt;&gt; &gt;&gt; process. ( this will be the toughest part)<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; -- elog.c and elog.h files needs some cleanups and changes ( to remove<br>
&gt;&gt;&gt; &gt;&gt; unwanted functions and data members of ErrorData structure) but this<br>
&gt;&gt;&gt; will<br>
&gt;&gt;&gt; &gt;&gt; be done at the end when we will have 100% surety if something in there<br>
&gt;&gt;&gt; is<br>
&gt;&gt;&gt; &gt;&gt; required or not.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; Thanks<br>
&gt;&gt;&gt; &gt;&gt; Muhammad Usama<br>
&gt;&gt;&gt; &gt; _______________________________________________<br>
&gt;&gt;&gt; &gt; pgpool-hackers mailing list<br>
&gt;&gt;&gt; &gt; <a href="mailto:pgpool-hackers@pgpool.net">pgpool-hackers@pgpool.net</a><br>
&gt;&gt;&gt; &gt; <a href="http://www.pgpool.net/mailman/listinfo/pgpool-hackers" target="_blank">http://www.pgpool.net/mailman/listinfo/pgpool-hackers</a><br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; --- src/main/main.c<br>
&gt;&gt;&gt; +++ src/main/main.c<br>
&gt;&gt;&gt; @@ -499,1915 +-23,60 @@<br>
&gt;&gt;&gt;         fd = open(pool_config-&gt;pid_file_name, O_CREAT|O_WRONLY,<br>
&gt;&gt;&gt; S_IRUSR|S_IWUSR);<br>
&gt;&gt;&gt;         if (fd == -1)<br>
&gt;&gt;&gt;         {<br>
&gt;&gt;&gt; -               pool_error(&quot;could not open pid file as %s. reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               pool_shmem_exit(1);<br>
&gt;&gt;&gt; -               exit(1);<br>
&gt;&gt;&gt; +               ereport(FATAL,<br>
&gt;&gt;&gt; +                       (errmsg(&quot;could not open pid file as %s. reason:<br>
&gt;&gt;&gt; %s&quot;,<br>
&gt;&gt;&gt; +                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno))));<br>
&gt;&gt;&gt;         }<br>
&gt;&gt;&gt;         snprintf(pidbuf, sizeof(pidbuf), &quot;%d&quot;, (int)getpid());<br>
&gt;&gt;&gt;         if (write(fd, pidbuf, strlen(pidbuf)+1) == -1)<br>
&gt;&gt;&gt;         {<br>
&gt;&gt;&gt; -               pool_error(&quot;could not write pid file as %s. reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt;                 close(fd);<br>
&gt;&gt;&gt; -               pool_shmem_exit(1);<br>
&gt;&gt;&gt; -               exit(1);<br>
&gt;&gt;&gt; +               ereport(FATAL,<br>
&gt;&gt;&gt; +                       (errmsg(&quot;could not write pid file as %s. reason:<br>
&gt;&gt;&gt; %s&quot;,<br>
&gt;&gt;&gt; +                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno))));<br>
&gt;&gt;&gt;         }<br>
&gt;&gt;&gt;         if (fsync(fd) == -1)<br>
&gt;&gt;&gt;         {<br>
&gt;&gt;&gt; -               pool_error(&quot;could not fsync pid file as %s. reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt;                 close(fd);<br>
&gt;&gt;&gt; -               pool_shmem_exit(1);<br>
&gt;&gt;&gt; -               exit(1);<br>
&gt;&gt;&gt; +               ereport(FATAL,<br>
&gt;&gt;&gt; +                       (errmsg(&quot;could not fsync pid file as %s. reason:<br>
&gt;&gt;&gt; %s&quot;,<br>
&gt;&gt;&gt; +                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno))));<br>
&gt;&gt;&gt;         }<br>
&gt;&gt;&gt;         if (close(fd) == -1)<br>
&gt;&gt;&gt;         {<br>
&gt;&gt;&gt; -               pool_error(&quot;could not close pid file as %s. reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               pool_shmem_exit(1);<br>
&gt;&gt;&gt; -               exit(1);<br>
&gt;&gt;&gt; +               ereport(FATAL,<br>
&gt;&gt;&gt; +                       (errmsg(&quot;could not close pid file as %s. reason:<br>
&gt;&gt;&gt; %s&quot;,<br>
&gt;&gt;&gt; +                                  pool_config-&gt;pid_file_name,<br>
&gt;&gt;&gt; strerror(errno))));<br>
&gt;&gt;&gt;         }<br>
&gt;&gt;&gt; +       /* register the call back to delete the pid file at system exit */<br>
&gt;&gt;&gt; +       on_proc_exit(FileUnlink, (Datum) pool_config-&gt;pid_file_name);<br>
&gt;&gt;&gt;  }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;  /*<br>
&gt;&gt;&gt; -* Read the status file<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -static int read_status_file(bool discard_status)<br>
&gt;&gt;&gt; + * get_config_file_name: return full path of pgpool.conf.<br>
&gt;&gt;&gt; + */<br>
&gt;&gt;&gt; +char *get_config_file_name(void)<br>
&gt;&gt;&gt;  {<br>
&gt;&gt;&gt; -       FILE *fd;<br>
&gt;&gt;&gt; -       char fnamebuf[POOLMAXPATHLEN];<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -       bool someone_wakeup = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       snprintf(fnamebuf, sizeof(fnamebuf), &quot;%s/%s&quot;,<br>
&gt;&gt;&gt; pool_config-&gt;logdir, STATUS_FILE_NAME);<br>
&gt;&gt;&gt; -       fd = fopen(fnamebuf, &quot;r&quot;);<br>
&gt;&gt;&gt; -       if (!fd)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;Backend status file %s does not exist&quot;,<br>
&gt;&gt;&gt; fnamebuf);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * If discard_status is true, unlink pgpool_status and<br>
&gt;&gt;&gt; -        * do not restore previous status.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (discard_status)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               fclose(fd);<br>
&gt;&gt;&gt; -               if (unlink(fnamebuf) == 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;Backend status file %s discarded&quot;,<br>
&gt;&gt;&gt; fnamebuf);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_error(&quot;Failed to discard backend status file<br>
&gt;&gt;&gt; %s reason:%s&quot;, fnamebuf, strerror(errno));<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               return 0;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (fread(&amp;backend_rec, 1, sizeof(backend_rec), fd) !=<br>
&gt;&gt;&gt; sizeof(backend_rec))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;Could not read backend status file as %s.<br>
&gt;&gt;&gt; reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  fnamebuf, strerror(errno));<br>
&gt;&gt;&gt; -               fclose(fd);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       fclose(fd);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i=0;i&lt; pool_config-&gt;backend_desc-&gt;num_backends;i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (backend_rec.status[i] == CON_DOWN)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       BACKEND_INFO(i).backend_status = CON_DOWN;<br>
&gt;&gt;&gt; -                       pool_log(&quot;read_status_file: %d th backend is set<br>
&gt;&gt;&gt; to down status&quot;, i);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;<br>
&gt;&gt;&gt; -                       someone_wakeup = true;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * If no one woke up, we regard the status file bogus<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (someone_wakeup == false)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               for (i=0;i&lt; pool_config-&gt;backend_desc-&gt;num_backends;i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return 0;<br>
&gt;&gt;&gt; +       return conf_file;<br>
&gt;&gt;&gt;  }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;  /*<br>
&gt;&gt;&gt; -* Write the pid file<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -static int write_status_file(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       FILE *fd;<br>
&gt;&gt;&gt; -       char fnamebuf[POOLMAXPATHLEN];<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       snprintf(fnamebuf, sizeof(fnamebuf), &quot;%s/%s&quot;,<br>
&gt;&gt;&gt; pool_config-&gt;logdir, STATUS_FILE_NAME);<br>
&gt;&gt;&gt; -       fd = fopen(fnamebuf, &quot;w&quot;);<br>
&gt;&gt;&gt; -       if (!fd)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;Could not open status file %s&quot;, fnamebuf);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       memset(&amp;backend_rec, 0, sizeof(backend_rec));<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i=0;i&lt; pool_config-&gt;backend_desc-&gt;num_backends;i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               backend_rec.status[i] = BACKEND_INFO(i).backend_status;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (fwrite(&amp;backend_rec, 1, sizeof(backend_rec), fd) !=<br>
&gt;&gt;&gt; sizeof(backend_rec))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;Could not write backend status file as %s.<br>
&gt;&gt;&gt; reason: %s&quot;,<br>
&gt;&gt;&gt; -                                  fnamebuf, strerror(errno));<br>
&gt;&gt;&gt; -               fclose(fd);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       fclose(fd);<br>
&gt;&gt;&gt; -       return 0;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * fork a child for PCP<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -pid_t pcp_fork_a_child(int unix_fd, int inet_fd, char *pcp_conf_file)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t pid;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pid = fork();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pid == 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               close(pipe_fds[0]);<br>
&gt;&gt;&gt; -               close(pipe_fds[1]);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               myargv = save_ps_display_args(myargc, myargv);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* call PCP child main */<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               health_check_timer_expired = 0;<br>
&gt;&gt;&gt; -               reload_config_request = 0;<br>
&gt;&gt;&gt; -               run_as_pcp_child = true;<br>
&gt;&gt;&gt; -               pcp_do_child(unix_fd, inet_fd, pcp_conf_file);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (pid == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;fork() failed. reason: %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return pid;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; -* fork a child<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -pid_t fork_a_child(int unix_fd, int inet_fd, int id)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t pid;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pid = fork();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pid == 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* Before we unconditionally closed pipe_fds[0] and<br>
&gt;&gt;&gt; pipe_fds[1]<br>
&gt;&gt;&gt; -                * here, which is apparently wrong since in the start up<br>
&gt;&gt;&gt; of<br>
&gt;&gt;&gt; -                * pgpool, pipe(2) is not called yet and it mistakenly<br>
&gt;&gt;&gt; closes<br>
&gt;&gt;&gt; -                * fd 0. Now we check the fd &gt; 0 before close(), expecting<br>
&gt;&gt;&gt; -                * pipe returns fds greater than 0.  Note that we cannot<br>
&gt;&gt;&gt; -                * unconditionally remove close(2) calls since<br>
&gt;&gt;&gt; fork_a_child()<br>
&gt;&gt;&gt; -                * may be called *after* pgpool starting up.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               if (pipe_fds[0] &gt; 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       close(pipe_fds[0]);<br>
&gt;&gt;&gt; -                       close(pipe_fds[1]);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               myargv = save_ps_display_args(myargc, myargv);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* call child main */<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               health_check_timer_expired = 0;<br>
&gt;&gt;&gt; -               reload_config_request = 0;<br>
&gt;&gt;&gt; -               my_proc_id = id;<br>
&gt;&gt;&gt; -               run_as_pcp_child = false;<br>
&gt;&gt;&gt; -               do_child(unix_fd, inet_fd);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (pid == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;fork() failed. reason: %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return pid;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; -* fork worker child process<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -pid_t worker_fork_a_child()<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t pid;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pid = fork();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pid == 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* Before we unconditionally closed pipe_fds[0] and<br>
&gt;&gt;&gt; pipe_fds[1]<br>
&gt;&gt;&gt; -                * here, which is apparently wrong since in the start up<br>
&gt;&gt;&gt; of<br>
&gt;&gt;&gt; -                * pgpool, pipe(2) is not called yet and it mistakenly<br>
&gt;&gt;&gt; closes<br>
&gt;&gt;&gt; -                * fd 0. Now we check the fd &gt; 0 before close(), expecting<br>
&gt;&gt;&gt; -                * pipe returns fds greater than 0.  Note that we cannot<br>
&gt;&gt;&gt; -                * unconditionally remove close(2) calls since<br>
&gt;&gt;&gt; fork_a_child()<br>
&gt;&gt;&gt; -                * may be called *after* pgpool starting up.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               if (pipe_fds[0] &gt; 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       close(pipe_fds[0]);<br>
&gt;&gt;&gt; -                       close(pipe_fds[1]);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               myargv = save_ps_display_args(myargc, myargv);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* call child main */<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               health_check_timer_expired = 0;<br>
&gt;&gt;&gt; -               reload_config_request = 0;<br>
&gt;&gt;&gt; -               do_worker_child();<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (pid == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;fork() failed. reason: %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return pid;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; -* create inet domain socket<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -static int create_inet_domain_socket(const char *hostname, const int<br>
&gt;&gt;&gt; port)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       struct sockaddr_in addr;<br>
&gt;&gt;&gt; -       int fd;<br>
&gt;&gt;&gt; -       int status;<br>
&gt;&gt;&gt; -       int one = 1;<br>
&gt;&gt;&gt; -       int len;<br>
&gt;&gt;&gt; -       int backlog;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       fd = socket(AF_INET, SOCK_STREAM, 0);<br>
&gt;&gt;&gt; -       if (fd == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;Failed to create INET domain socket. reason:<br>
&gt;&gt;&gt; %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &amp;one,<br>
&gt;&gt;&gt; -                                       sizeof(one))) == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;setsockopt() failed. reason: %s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       memset((char *) &amp;addr, 0, sizeof(addr));<br>
&gt;&gt;&gt; -       addr.sin_family = AF_INET;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (strcmp(hostname, &quot;*&quot;)==0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               addr.sin_addr.s_addr = htonl(INADDR_ANY);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               struct hostent *hostinfo;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               hostinfo = gethostbyname(hostname);<br>
&gt;&gt;&gt; -               if (!hostinfo)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_error(&quot;could not resolve host name \&quot;%s\&quot;:<br>
&gt;&gt;&gt; %s&quot;, hostname, hstrerror(h_errno));<br>
&gt;&gt;&gt; -                       myexit(1);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               addr.sin_addr = *(struct in_addr *) hostinfo-&gt;h_addr;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       addr.sin_port = htons(port);<br>
&gt;&gt;&gt; -       len = sizeof(struct sockaddr_in);<br>
&gt;&gt;&gt; -       status = bind(fd, (struct sockaddr *)&amp;addr, len);<br>
&gt;&gt;&gt; -       if (status == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               char *host = &quot;&quot;, *serv = &quot;&quot;;<br>
&gt;&gt;&gt; -               char hostname[NI_MAXHOST], servname[NI_MAXSERV];<br>
&gt;&gt;&gt; -               if (getnameinfo((struct sockaddr *) &amp;addr, len, hostname,<br>
&gt;&gt;&gt; sizeof(hostname), servname, sizeof(servname), 0) == 0) {<br>
&gt;&gt;&gt; -                       host = hostname;<br>
&gt;&gt;&gt; -                       serv = servname;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               pool_error(&quot;bind(%s:%s) failed. reason: %s&quot;, host, serv,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       backlog = pool_config-&gt;num_init_children * 2;<br>
&gt;&gt;&gt; -       if (backlog &gt; PGPOOLMAXLITSENQUEUELENGTH)<br>
&gt;&gt;&gt; -               backlog = PGPOOLMAXLITSENQUEUELENGTH;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       status = listen(fd, backlog);<br>
&gt;&gt;&gt; -       if (status &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;listen() failed. reason: %s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return fd;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; -* create UNIX domain socket<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -static int create_unix_domain_socket(struct sockaddr_un un_addr_tmp)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       struct sockaddr_un addr;<br>
&gt;&gt;&gt; -       int fd;<br>
&gt;&gt;&gt; -       int status;<br>
&gt;&gt;&gt; -       int len;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       fd = socket(AF_UNIX, SOCK_STREAM, 0);<br>
&gt;&gt;&gt; -       if (fd == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;Failed to create UNIX domain socket. reason:<br>
&gt;&gt;&gt; %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       memset((char *) &amp;addr, 0, sizeof(addr));<br>
&gt;&gt;&gt; -       addr.sun_family = AF_UNIX;<br>
&gt;&gt;&gt; -       snprintf(addr.sun_path, sizeof(addr.sun_path), &quot;%s&quot;,<br>
&gt;&gt;&gt; un_addr_tmp.sun_path);<br>
&gt;&gt;&gt; -       len = sizeof(struct sockaddr_un);<br>
&gt;&gt;&gt; -       status = bind(fd, (struct sockaddr *)&amp;addr, len);<br>
&gt;&gt;&gt; -       if (status == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;bind(%s) failed. reason: %s&quot;, addr.sun_path,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (chmod(un_addr_tmp.sun_path, 0777) == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;chmod() failed. reason: %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       status = listen(fd, PGPOOLMAXLITSENQUEUELENGTH);<br>
&gt;&gt;&gt; -       if (status &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;listen() failed. reason: %s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               myexit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return fd;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static void myunlink(const char* path)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       if (unlink(path) == 0) return;<br>
&gt;&gt;&gt; -       pool_error(&quot;unlink(%s) failed: %s&quot;, path, strerror(errno));<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static void myexit(int code)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (getpid() != mypid)<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (process_info != NULL) {<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;AuthBlockSig);<br>
&gt;&gt;&gt; -               exiting = 1;<br>
&gt;&gt;&gt; -               for (i = 0; i &lt; pool_config-&gt;num_init_children; i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pid_t pid = process_info[i].pid;<br>
&gt;&gt;&gt; -                       if (pid)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               kill(pid, SIGTERM);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* wait for all children to exit */<br>
&gt;&gt;&gt; -               while (wait(NULL) &gt; 0)<br>
&gt;&gt;&gt; -                       ;<br>
&gt;&gt;&gt; -               if (errno != ECHILD)<br>
&gt;&gt;&gt; -                       pool_error(&quot;wait() failed. reason:%s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       myunlink(un_addr.sun_path);<br>
&gt;&gt;&gt; -       myunlink(pcp_un_addr.sun_path);<br>
&gt;&gt;&gt; -       myunlink(pool_config-&gt;pid_file_name);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       write_status_file();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_shmem_exit(code);<br>
&gt;&gt;&gt; -       exit(code);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -void notice_backend_error(int node_id)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int n = node_id;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (getpid() == mypid)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;notice_backend_error: called from pgpool main.<br>
&gt;&gt;&gt; ignored.&quot;);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               degenerate_backend_set(&amp;n, 1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/* notice backend connection error using SIGUSR1 */<br>
&gt;&gt;&gt; -void degenerate_backend_set(int *node_id_set, int count)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t parent = getppid();<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -       bool need_signal = false;<br>
&gt;&gt;&gt; -#ifdef HAVE_SIGPROCMASK<br>
&gt;&gt;&gt; -       sigset_t oldmask;<br>
&gt;&gt;&gt; -#else<br>
&gt;&gt;&gt; -       int     oldmask;<br>
&gt;&gt;&gt; -#endif<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pool_config-&gt;parallel_mode)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       POOL_SETMASK2(&amp;BlockSig, &amp;oldmask);<br>
&gt;&gt;&gt; -       pool_semaphore_lock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -       Req_info-&gt;kind = NODE_DOWN_REQUEST;<br>
&gt;&gt;&gt; -       for (i = 0; i &lt; count; i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (node_id_set[i] &lt; 0 || node_id_set[i] &gt;=<br>
&gt;&gt;&gt; MAX_NUM_BACKENDS ||<br>
&gt;&gt;&gt; -                       !VALID_BACKEND(node_id_set[i]))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;degenerate_backend_set: node %d is not<br>
&gt;&gt;&gt; valid backend.&quot;, i);<br>
&gt;&gt;&gt; -                       continue;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               if<br>
&gt;&gt;&gt; (POOL_DISALLOW_TO_FAILOVER(BACKEND_INFO(node_id_set[i]).flag))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;degenerate_backend_set: %d failover<br>
&gt;&gt;&gt; request from pid %d is canceled because failover is disallowed&quot;,<br>
&gt;&gt;&gt; node_id_set[i], getpid());<br>
&gt;&gt;&gt; -                       continue;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               pool_log(&quot;degenerate_backend_set: %d fail over request<br>
&gt;&gt;&gt; from pid %d&quot;, node_id_set[i], getpid());<br>
&gt;&gt;&gt; -               Req_info-&gt;node_id[i] = node_id_set[i];<br>
&gt;&gt;&gt; -               need_signal = true;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (need_signal)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (!pool_config-&gt;use_watchdog || WD_OK ==<br>
&gt;&gt;&gt; wd_degenerate_backend_set(node_id_set, count))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       kill(parent, SIGUSR1);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;degenerate_backend_set: failover<br>
&gt;&gt;&gt; request from pid %d is canceled by other pgpool&quot;, getpid());<br>
&gt;&gt;&gt; -                       memset(Req_info-&gt;node_id, -1, sizeof(int) *<br>
&gt;&gt;&gt; MAX_NUM_BACKENDS);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;oldmask);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/* send promote node request using SIGUSR1 */<br>
&gt;&gt;&gt; -void promote_backend(int node_id)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t parent = getppid();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (!MASTER_SLAVE || strcmp(pool_config-&gt;master_slave_sub_mode,<br>
&gt;&gt;&gt; MODE_STREAMREP))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (node_id &lt; 0 || node_id &gt;= MAX_NUM_BACKENDS ||<br>
&gt;&gt;&gt; !VALID_BACKEND(node_id))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;promote_backend: node %d is not valid<br>
&gt;&gt;&gt; backend.&quot;, node_id);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_semaphore_lock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -       Req_info-&gt;kind = PROMOTE_NODE_REQUEST;<br>
&gt;&gt;&gt; -       Req_info-&gt;node_id[0] = node_id;<br>
&gt;&gt;&gt; -       pool_log(&quot;promote_backend: %d promote node request from pid %d&quot;,<br>
&gt;&gt;&gt; node_id, getpid());<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (!pool_config-&gt;use_watchdog || WD_OK ==<br>
&gt;&gt;&gt; wd_promote_backend(node_id))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               kill(parent, SIGUSR1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;promote_backend: promote request from pid %d is<br>
&gt;&gt;&gt; canceled by other pgpool&quot;, getpid());<br>
&gt;&gt;&gt; -               Req_info-&gt;node_id[0] = -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/* send failback request using SIGUSR1 */<br>
&gt;&gt;&gt; -void send_failback_request(int node_id)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t parent = getppid();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_log(&quot;send_failback_request: fail back %d th node request<br>
&gt;&gt;&gt; from pid %d&quot;, node_id, getpid());<br>
&gt;&gt;&gt; -       Req_info-&gt;kind = NODE_UP_REQUEST;<br>
&gt;&gt;&gt; -       Req_info-&gt;node_id[0] = node_id;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -    if (node_id &lt; 0 || node_id &gt;= MAX_NUM_BACKENDS ||<br>
&gt;&gt;&gt; -               (RAW_MODE &amp;&amp; BACKEND_INFO(node_id).backend_status !=<br>
&gt;&gt;&gt; CON_DOWN &amp;&amp; VALID_BACKEND(node_id)))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;send_failback_request: node %d is alive.&quot;,<br>
&gt;&gt;&gt; node_id);<br>
&gt;&gt;&gt; -               Req_info-&gt;node_id[0] = -1;<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog &amp;&amp; WD_OK !=<br>
&gt;&gt;&gt; wd_send_failback_request(node_id))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;send_failback_request: failback request from<br>
&gt;&gt;&gt; pid %d is canceled by other pgpool&quot;, getpid());<br>
&gt;&gt;&gt; -               Req_info-&gt;node_id[0] = -1;<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       kill(parent, SIGUSR1);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static RETSIGTYPE exit_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;AuthBlockSig);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * this could happen in a child process if a signal has been sent<br>
&gt;&gt;&gt; -        * before resetting signal handler<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (getpid() != mypid)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;exit_handler: I am not parent&quot;);<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               pool_shmem_exit(0);<br>
&gt;&gt;&gt; -               exit(0);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (sig == SIGTERM)<br>
&gt;&gt;&gt; -               pool_log(&quot;received smart shutdown request&quot;);<br>
&gt;&gt;&gt; -       else if (sig == SIGINT)<br>
&gt;&gt;&gt; -               pool_log(&quot;received fast shutdown request&quot;);<br>
&gt;&gt;&gt; -       else if (sig == SIGQUIT)<br>
&gt;&gt;&gt; -               pool_log(&quot;received immediate shutdown request&quot;);<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;exit_handler: unknown signal received %d&quot;,<br>
&gt;&gt;&gt; sig);<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       exiting = 1;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i = 0; i &lt; pool_config-&gt;num_init_children; i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pid_t pid = process_info[i].pid;<br>
&gt;&gt;&gt; -               if (pid)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       kill(pid, sig);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       kill(pcp_pid, sig);<br>
&gt;&gt;&gt; -       kill(worker_pid, sig);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               wd_kill_watchdog(sig);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       while (wait(NULL) &gt; 0)<br>
&gt;&gt;&gt; -               ;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (errno != ECHILD)<br>
&gt;&gt;&gt; -               pool_error(&quot;wait() failed. reason:%s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       process_info = NULL;<br>
&gt;&gt;&gt; -       myexit(0);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * Calculate next valid master node id.<br>
&gt;&gt;&gt; - * If no valid node found, returns -1.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int get_next_master_node(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i=0;i&lt;pool_config-&gt;backend_desc-&gt;num_backends;i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /*<br>
&gt;&gt;&gt; -                * Do not use VALID_BACKEND macro in raw mode.<br>
&gt;&gt;&gt; -                * VALID_BACKEND return true only if the argument is<br>
&gt;&gt;&gt; master<br>
&gt;&gt;&gt; -                * node id. In other words, standby nodes are false. So<br>
&gt;&gt;&gt; need<br>
&gt;&gt;&gt; -                * to check backend status with VALID_BACKEND_RAW.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               if (RAW_MODE)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (VALID_BACKEND_RAW(i))<br>
&gt;&gt;&gt; -                               break;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (VALID_BACKEND(i))<br>
&gt;&gt;&gt; -                               break;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (i == pool_config-&gt;backend_desc-&gt;num_backends)<br>
&gt;&gt;&gt; -               i = -1;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return i;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * handle SIGUSR1<br>
&gt;&gt;&gt; - *<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static RETSIGTYPE failover_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -       failover_request = 1;<br>
&gt;&gt;&gt; -       write(pipe_fds[1], &quot;\0&quot;, 1);<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * backend connection error, failover/failback request, if possible<br>
&gt;&gt;&gt; - * failover() must be called under protecting signals.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static void failover(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -       int node_id;<br>
&gt;&gt;&gt; -       bool by_health_check;<br>
&gt;&gt;&gt; -       int new_master;<br>
&gt;&gt;&gt; -       int new_primary;<br>
&gt;&gt;&gt; -       int nodes[MAX_NUM_BACKENDS];<br>
&gt;&gt;&gt; -       bool need_to_restart_children;<br>
&gt;&gt;&gt; -       int status;<br>
&gt;&gt;&gt; -       int sts;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_debug(&quot;failover_handler called&quot;);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       memset(nodes, 0, sizeof(int) * MAX_NUM_BACKENDS);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * this could happen in a child process if a signal has been sent<br>
&gt;&gt;&gt; -        * before resetting signal handler<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (getpid() != mypid)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;failover_handler: I am not parent&quot;);<br>
&gt;&gt;&gt; -               kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * processing SIGTERM, SIGINT or SIGQUIT<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (exiting)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;failover_handler called while exiting&quot;);<br>
&gt;&gt;&gt; -               kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * processing fail over or switch over<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (switching)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;failover_handler called while switching&quot;);<br>
&gt;&gt;&gt; -               kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_semaphore_lock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (Req_info-&gt;kind == CLOSE_IDLE_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -               kill_all_children(SIGUSR1);<br>
&gt;&gt;&gt; -               kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * if not in replication mode/master slave mode, we treat this a<br>
&gt;&gt;&gt; restart request.<br>
&gt;&gt;&gt; -        * otherwise we need to check if we have already failovered.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       pool_debug(&quot;failover_handler: starting to select new master<br>
&gt;&gt;&gt; node&quot;);<br>
&gt;&gt;&gt; -       switching = 1;<br>
&gt;&gt;&gt; -       Req_info-&gt;switching = true;<br>
&gt;&gt;&gt; -       node_id = Req_info-&gt;node_id[0];<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* start of command inter-lock with watchdog */<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               by_health_check = (!failover_request &amp;&amp;<br>
&gt;&gt;&gt; Req_info-&gt;kind==NODE_DOWN_REQUEST);<br>
&gt;&gt;&gt; -               wd_start_interlock(by_health_check);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* failback request? */<br>
&gt;&gt;&gt; -       if (Req_info-&gt;kind == NODE_UP_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (node_id &gt;= MAX_NUM_BACKENDS ||<br>
&gt;&gt;&gt; -                       (Req_info-&gt;kind == NODE_UP_REQUEST &amp;&amp; !(RAW_MODE<br>
&gt;&gt;&gt; &amp;&amp;<br>
&gt;&gt;&gt; -            BACKEND_INFO(node_id).backend_status == CON_DOWN) &amp;&amp;<br>
&gt;&gt;&gt; VALID_BACKEND(node_id)) ||<br>
&gt;&gt;&gt; -                       (Req_info-&gt;kind == NODE_DOWN_REQUEST &amp;&amp;<br>
&gt;&gt;&gt; !VALID_BACKEND(node_id)))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -                       pool_error(&quot;failover_handler: invalid node_id %d<br>
&gt;&gt;&gt; status:%d MAX_NUM_BACKENDS: %d&quot;, node_id,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_status, MAX_NUM_BACKENDS);<br>
&gt;&gt;&gt; -                       kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -                       switching = 0;<br>
&gt;&gt;&gt; -                       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* end of command inter-lock */<br>
&gt;&gt;&gt; -                       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                               wd_leave_interlock();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       return;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               pool_log(&quot;starting fail back. reconnect host %s(%d)&quot;,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -               BACKEND_INFO(node_id).backend_status = CON_CONNECT_WAIT;<br>
&gt;&gt;&gt;        /* unset down status */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* wait for failback command lock or to be lock holder */<br>
&gt;&gt;&gt; -               if (pool_config-&gt;use_watchdog &amp;&amp; !wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       wd_wait_for_lock(WD_FAILBACK_COMMAND_LOCK);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               /* execute failback command if lock holder */<br>
&gt;&gt;&gt; -               if (!pool_config-&gt;use_watchdog || wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       trigger_failover_command(node_id,<br>
&gt;&gt;&gt; pool_config-&gt;failback_command,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; MASTER_NODE_ID, get_next_master_node(), PRIMARY_NODE_ID);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* unlock failback command */<br>
&gt;&gt;&gt; -                       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                               wd_unlock(WD_FAILBACK_COMMAND_LOCK);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (Req_info-&gt;kind == PROMOTE_NODE_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (node_id != -1 &amp;&amp; VALID_BACKEND(node_id))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;starting promotion. promote host<br>
&gt;&gt;&gt; %s(%d)&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;failover: no backends are promoted&quot;);<br>
&gt;&gt;&gt; -                       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -                       kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -                       switching = 0;<br>
&gt;&gt;&gt; -                       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* end of command inter-lock */<br>
&gt;&gt;&gt; -                       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                               wd_leave_interlock();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       return;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               int cnt = 0;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               for (i = 0; i &lt; MAX_NUM_BACKENDS; i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (Req_info-&gt;node_id[i] != -1 &amp;&amp;<br>
&gt;&gt;&gt; -                               ((RAW_MODE &amp;&amp;<br>
&gt;&gt;&gt; VALID_BACKEND_RAW(Req_info-&gt;node_id[i])) ||<br>
&gt;&gt;&gt; -                                VALID_BACKEND(Req_info-&gt;node_id[i])))<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_log(&quot;starting degeneration. shutdown<br>
&gt;&gt;&gt; host %s(%d)&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(Req_info-&gt;node_id[i]).backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(Req_info-&gt;node_id[i]).backend_port);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; BACKEND_INFO(Req_info-&gt;node_id[i]).backend_status = CON_DOWN;   /* set down<br>
&gt;&gt;&gt; status */<br>
&gt;&gt;&gt; -                               /* save down node */<br>
&gt;&gt;&gt; -                               nodes[Req_info-&gt;node_id[i]] = 1;<br>
&gt;&gt;&gt; -                               cnt++;<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               if (cnt == 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;failover: no backends are degenerated&quot;);<br>
&gt;&gt;&gt; -                       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -                       kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -                       switching = 0;<br>
&gt;&gt;&gt; -                       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* end of command inter-lock */<br>
&gt;&gt;&gt; -                       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                               wd_leave_interlock();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       return;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       new_master = get_next_master_node();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (new_master &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;failover_handler: no valid DB node found&quot;);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * Before we tried to minimize restarting pgpool to protect existing<br>
&gt;&gt;&gt; - * connections from clients to pgpool children. What we did here was,<br>
&gt;&gt;&gt; - * if children other than master went down, we did not fail over.<br>
&gt;&gt;&gt; - * This is wrong. Think about following scenario. If someone<br>
&gt;&gt;&gt; - * accidentally plugs out the network cable, the TCP/IP stack keeps<br>
&gt;&gt;&gt; - * retrying for long time (typically 2 hours). The only way to stop<br>
&gt;&gt;&gt; - * the retry is restarting the process.  Bottom line is, we need to<br>
&gt;&gt;&gt; - * restart all children in any case.  See pgpool-general list posting<br>
&gt;&gt;&gt; - * &quot;TCP connections are *not* closed when a backend timeout&quot; on Jul 13<br>
&gt;&gt;&gt; - * 2008 for more details.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -#ifdef NOT_USED<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (Req_info-&gt;master_node_id == new_master &amp;&amp; *InRecovery<br>
&gt;&gt;&gt; == RECOVERY_INIT)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;failover_handler: do not restart<br>
&gt;&gt;&gt; pgpool. same master node %d was selected&quot;, new_master);<br>
&gt;&gt;&gt; -                       if (Req_info-&gt;kind == NODE_UP_REQUEST)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_log(&quot;failback done. reconnect host<br>
&gt;&gt;&gt; %s(%d)&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_log(&quot;failover done. shutdown host<br>
&gt;&gt;&gt; %s(%d)&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* exec failover_command */<br>
&gt;&gt;&gt; -                       for (i = 0; i &lt;<br>
&gt;&gt;&gt; pool_config-&gt;backend_desc-&gt;num_backends; i++)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               if (nodes[i])<br>
&gt;&gt;&gt; -                                       trigger_failover_command(i,<br>
&gt;&gt;&gt; pool_config-&gt;failover_command);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -                       switching = 0;<br>
&gt;&gt;&gt; -                       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -                       kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -                       switching = 0;<br>
&gt;&gt;&gt; -                       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -                       return;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -#endif<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -   /* On 2011/5/2 Tatsuo Ishii says: if mode is streaming replication<br>
&gt;&gt;&gt; -       * and request is NODE_UP_REQUEST(failback case) we don&#39;t need to<br>
&gt;&gt;&gt; -       * restart all children. Existing session will not use newly<br>
&gt;&gt;&gt; -       * attached node, but load balanced node is not changed until this<br>
&gt;&gt;&gt; -       * session ends, so it&#39;s harmless anyway.<br>
&gt;&gt;&gt; -       */<br>
&gt;&gt;&gt; -       if (MASTER_SLAVE &amp;&amp; !strcmp(pool_config-&gt;master_slave_sub_mode,<br>
&gt;&gt;&gt; MODE_STREAMREP) &amp;&amp;<br>
&gt;&gt;&gt; -               Req_info-&gt;kind == NODE_UP_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;Do not restart children because we are<br>
&gt;&gt;&gt; failbacking node id %d host%s port:%d and we are in streaming replication<br>
&gt;&gt;&gt; mode&quot;, node_id,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               need_to_restart_children = false;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;Restart all children&quot;);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* kill all children */<br>
&gt;&gt;&gt; -               for (i = 0; i &lt; pool_config-&gt;num_init_children; i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pid_t pid = process_info[i].pid;<br>
&gt;&gt;&gt; -                       if (pid)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               kill(pid, SIGQUIT);<br>
&gt;&gt;&gt; -                               pool_debug(&quot;failover_handler: kill %d&quot;,<br>
&gt;&gt;&gt; pid);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               need_to_restart_children = true;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* wait for failover command lock or to be lock holder*/<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog &amp;&amp; !wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               wd_wait_for_lock(WD_FAILOVER_COMMAND_LOCK);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* execute failover command if lock holder */<br>
&gt;&gt;&gt; -       if (!pool_config-&gt;use_watchdog || wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* Exec failover_command if needed */<br>
&gt;&gt;&gt; -               for (i = 0; i &lt; pool_config-&gt;backend_desc-&gt;num_backends;<br>
&gt;&gt;&gt; i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (nodes[i])<br>
&gt;&gt;&gt; -                               trigger_failover_command(i,<br>
&gt;&gt;&gt; pool_config-&gt;failover_command,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;               MASTER_NODE_ID, new_master, PRIMARY_NODE_ID);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* unlock failover command */<br>
&gt;&gt;&gt; -               if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                       wd_unlock(WD_FAILOVER_COMMAND_LOCK);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/* no need to wait since it will be done in reap_handler */<br>
&gt;&gt;&gt; -#ifdef NOT_USED<br>
&gt;&gt;&gt; -       while (wait(NULL) &gt; 0)<br>
&gt;&gt;&gt; -               ;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (errno != ECHILD)<br>
&gt;&gt;&gt; -               pool_error(&quot;failover_handler: wait() failed. reason:%s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -#endif<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (Req_info-&gt;kind == PROMOTE_NODE_REQUEST &amp;&amp;<br>
&gt;&gt;&gt; VALID_BACKEND(node_id))<br>
&gt;&gt;&gt; -               new_primary = node_id;<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -               new_primary =  find_primary_node_repeatedly();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * If follow_master_command is provided and in master/slave<br>
&gt;&gt;&gt; -        * streaming replication mode, we start degenerating all backends<br>
&gt;&gt;&gt; -        * as they are not replicated anymore.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       int follow_cnt = 0;<br>
&gt;&gt;&gt; -       if (MASTER_SLAVE &amp;&amp; !strcmp(pool_config-&gt;master_slave_sub_mode,<br>
&gt;&gt;&gt; MODE_STREAMREP))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (*pool_config-&gt;follow_master_command != &#39;\0&#39; ||<br>
&gt;&gt;&gt; -                       Req_info-&gt;kind == PROMOTE_NODE_REQUEST)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       /* only if the failover is against the current<br>
&gt;&gt;&gt; primary */<br>
&gt;&gt;&gt; -                       if (((Req_info-&gt;kind == NODE_DOWN_REQUEST) &amp;&amp;<br>
&gt;&gt;&gt; -                                (nodes[Req_info-&gt;primary_node_id])) ||<br>
&gt;&gt;&gt; -                               ((Req_info-&gt;kind == PROMOTE_NODE_REQUEST)<br>
&gt;&gt;&gt; &amp;&amp;<br>
&gt;&gt;&gt; -                                (VALID_BACKEND(node_id)))) {<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                               for (i = 0; i &lt;<br>
&gt;&gt;&gt; pool_config-&gt;backend_desc-&gt;num_backends; i++)<br>
&gt;&gt;&gt; -                               {<br>
&gt;&gt;&gt; -                                       /* do not degenerate the new<br>
&gt;&gt;&gt; primary */<br>
&gt;&gt;&gt; -                                       if ((new_primary &gt;= 0) &amp;&amp; (i !=<br>
&gt;&gt;&gt; new_primary)) {<br>
&gt;&gt;&gt; -                                               BackendInfo *bkinfo;<br>
&gt;&gt;&gt; -                                               bkinfo =<br>
&gt;&gt;&gt; pool_get_node_info(i);<br>
&gt;&gt;&gt; -                                               pool_log(&quot;starting follow<br>
&gt;&gt;&gt; degeneration. shutdown host %s(%d)&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  bkinfo-&gt;backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  bkinfo-&gt;backend_port);<br>
&gt;&gt;&gt; -                                               bkinfo-&gt;backend_status =<br>
&gt;&gt;&gt; CON_DOWN;      /* set down status */<br>
&gt;&gt;&gt; -                                               follow_cnt++;<br>
&gt;&gt;&gt; -                                       }<br>
&gt;&gt;&gt; -                               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                               if (follow_cnt == 0)<br>
&gt;&gt;&gt; -                               {<br>
&gt;&gt;&gt; -                                       pool_log(&quot;failover: no follow<br>
&gt;&gt;&gt; backends are degenerated&quot;);<br>
&gt;&gt;&gt; -                               }<br>
&gt;&gt;&gt; -                               else<br>
&gt;&gt;&gt; -                               {<br>
&gt;&gt;&gt; -                                       /* update new master node */<br>
&gt;&gt;&gt; -                                       new_master =<br>
&gt;&gt;&gt; get_next_master_node();<br>
&gt;&gt;&gt; -                                       pool_log(&quot;failover: %d follow<br>
&gt;&gt;&gt; backends have been degenerated&quot;, follow_cnt);<br>
&gt;&gt;&gt; -                               }<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       memset(Req_info-&gt;node_id, -1, sizeof(int) * MAX_NUM_BACKENDS);<br>
&gt;&gt;&gt; -       pool_semaphore_unlock(REQUEST_INFO_SEM);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* wait for follow_master_command lock or to be lock holder */<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog &amp;&amp; !wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               wd_wait_for_lock(WD_FOLLOW_MASTER_COMMAND_LOCK);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* execute follow_master_command */<br>
&gt;&gt;&gt; -       if (!pool_config-&gt;use_watchdog || wd_am_I_lock_holder())<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if ((follow_cnt &gt; 0) &amp;&amp;<br>
&gt;&gt;&gt; (*pool_config-&gt;follow_master_command != &#39;\0&#39;))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       follow_pid =<br>
&gt;&gt;&gt; fork_follow_child(Req_info-&gt;master_node_id, new_primary,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;       Req_info-&gt;primary_node_id);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* unlock follow_master_command  */<br>
&gt;&gt;&gt; -               if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -                       wd_unlock(WD_FOLLOW_MASTER_COMMAND_LOCK);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* end of command inter-lock */<br>
&gt;&gt;&gt; -       if (pool_config-&gt;use_watchdog)<br>
&gt;&gt;&gt; -               wd_end_interlock();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* Save primary node id */<br>
&gt;&gt;&gt; -       Req_info-&gt;primary_node_id = new_primary;<br>
&gt;&gt;&gt; -       pool_log(&quot;failover: set new primary node: %d&quot;,<br>
&gt;&gt;&gt; Req_info-&gt;primary_node_id);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (new_master &gt;= 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               Req_info-&gt;master_node_id = new_master;<br>
&gt;&gt;&gt; -               pool_log(&quot;failover: set new master node: %d&quot;,<br>
&gt;&gt;&gt; Req_info-&gt;master_node_id);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* Fork the children if needed */<br>
&gt;&gt;&gt; -       if (need_to_restart_children)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               for (i=0;i&lt;pool_config-&gt;num_init_children;i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /*<br>
&gt;&gt;&gt; -                        * Try to kill pgpool child because previous kill<br>
&gt;&gt;&gt; signal<br>
&gt;&gt;&gt; -                        * may not be received by pgpool child. This<br>
&gt;&gt;&gt; could happen<br>
&gt;&gt;&gt; -                        * if multiple PostgreSQL are going down (or even<br>
&gt;&gt;&gt; starting<br>
&gt;&gt;&gt; -                        * pgpool, without starting PostgreSQL can<br>
&gt;&gt;&gt; trigger this).<br>
&gt;&gt;&gt; -                        * Child calls degenerate_backend() and it tries<br>
&gt;&gt;&gt; to aquire<br>
&gt;&gt;&gt; -                        * semaphore to write a failover request. In this<br>
&gt;&gt;&gt; case the<br>
&gt;&gt;&gt; -                        * signal mask is set as well, thus signals are<br>
&gt;&gt;&gt; never<br>
&gt;&gt;&gt; -                        * received.<br>
&gt;&gt;&gt; -                        */<br>
&gt;&gt;&gt; -                       kill(process_info[i].pid, SIGQUIT);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       process_info[i].pid = fork_a_child(unix_fd,<br>
&gt;&gt;&gt; inet_fd, i);<br>
&gt;&gt;&gt; -                       process_info[i].start_time = time(NULL);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* Set restart request to each child. Children will<br>
&gt;&gt;&gt; exit(1)<br>
&gt;&gt;&gt; -                * whenever they are idle to restart.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               for (i=0;i&lt;pool_config-&gt;num_init_children;i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       process_info[i].need_to_restart = 1;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * Send restart request to worker child.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       kill(worker_pid, SIGUSR1);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (Req_info-&gt;kind == NODE_UP_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;failback done. reconnect host %s(%d)&quot;,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (Req_info-&gt;kind == PROMOTE_NODE_REQUEST)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;promotion done. promoted host %s(%d)&quot;,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;failover done. shutdown host %s(%d)&quot;,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_hostname,<br>
&gt;&gt;&gt; -                                BACKEND_INFO(node_id).backend_port);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       switching = 0;<br>
&gt;&gt;&gt; -       Req_info-&gt;switching = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* kick wakeup_handler in pcp_child to notice that<br>
&gt;&gt;&gt; -        * failover/failback done<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       kill(pcp_pid, SIGUSR2);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       sleep(1);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * Send restart request to pcp child.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       kill(pcp_pid, SIGUSR1);<br>
&gt;&gt;&gt; -       for (;;)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               sts = waitpid(pcp_pid, &amp;status, 0);<br>
&gt;&gt;&gt; -               if (sts != -1)<br>
&gt;&gt;&gt; -                       break;<br>
&gt;&gt;&gt; -               if (sts == -1)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (errno == EINTR)<br>
&gt;&gt;&gt; -                               continue;<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_error(&quot;failover: waitpid failed.<br>
&gt;&gt;&gt; reason: %s&quot;, strerror(errno));<br>
&gt;&gt;&gt; -                               return;<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       if (WIFSIGNALED(status))<br>
&gt;&gt;&gt; -               pool_log(&quot;PCP child %d exits with status %d by signal %d<br>
&gt;&gt;&gt; in failover()&quot;, pcp_pid, status, WTERMSIG(status));<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -               pool_log(&quot;PCP child %d exits with status %d in<br>
&gt;&gt;&gt; failover()&quot;, pcp_pid, status);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pcp_pid = pcp_fork_a_child(pcp_unix_fd, pcp_inet_fd,<br>
&gt;&gt;&gt; pcp_conf_file);<br>
&gt;&gt;&gt; -       pool_log(&quot;fork a new PCP child pid %d in failover()&quot;, pcp_pid);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * health check timer handler<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static RETSIGTYPE health_check_timer_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -       health_check_timer_expired = 1;<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * Check if we can connect to the backend<br>
&gt;&gt;&gt; - * returns 0 for OK. otherwise returns backend id + 1<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int health_check(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_CONNECTION_POOL_SLOT *slot;<br>
&gt;&gt;&gt; -       BackendInfo *bkinfo;<br>
&gt;&gt;&gt; -       static bool is_first = true;<br>
&gt;&gt;&gt; -       static char *dbname;<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* Do not execute health check during recovery */<br>
&gt;&gt;&gt; -       if (*InRecovery)<br>
&gt;&gt;&gt; -               return 0;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; - Retry:<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * First we try with &quot;postgres&quot; database.<br>
&gt;&gt;&gt; -        */<br>
&gt;&gt;&gt; -       if (is_first)<br>
&gt;&gt;&gt; -               dbname = &quot;postgres&quot;;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i=0;i&lt;pool_config-&gt;backend_desc-&gt;num_backends;i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /*<br>
&gt;&gt;&gt; -                * Make sure that health check timer has not been expired.<br>
&gt;&gt;&gt; -                * Before called health_check(),<br>
&gt;&gt;&gt; health_check_timer_expired is<br>
&gt;&gt;&gt; -                * set to 0.  However it is possible that while<br>
&gt;&gt;&gt; processing DB<br>
&gt;&gt;&gt; -                * nodes health check timer expired.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               if (health_check_timer_expired)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;health_check: health check timer has<br>
&gt;&gt;&gt; been already expired before attempting to connect to %d th backend&quot;, i);<br>
&gt;&gt;&gt; -                       return i+1;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               bkinfo = pool_get_node_info(i);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               pool_debug(&quot;health_check: %d th DB node status: %d&quot;, i,<br>
&gt;&gt;&gt; bkinfo-&gt;backend_status);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               if (bkinfo-&gt;backend_status == CON_UNUSED ||<br>
&gt;&gt;&gt; -                       bkinfo-&gt;backend_status == CON_DOWN)<br>
&gt;&gt;&gt; -                       continue;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               slot =<br>
&gt;&gt;&gt; make_persistent_db_connection(bkinfo-&gt;backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;                bkinfo-&gt;backend_port,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;                dbname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;                pool_config-&gt;health_check_user,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;                pool_config-&gt;health_check_password, false);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               if (is_first)<br>
&gt;&gt;&gt; -                       is_first = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               if (!slot)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       /*<br>
&gt;&gt;&gt; -                        * Retry with template1 unless health check timer<br>
&gt;&gt;&gt; is expired.<br>
&gt;&gt;&gt; -                        */<br>
&gt;&gt;&gt; -                       if (!strcmp(dbname, &quot;postgres&quot;) &amp;&amp;<br>
&gt;&gt;&gt; health_check_timer_expired == 0)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               dbname = &quot;template1&quot;;<br>
&gt;&gt;&gt; -                               goto Retry;<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_error(&quot;health check failed. %d th<br>
&gt;&gt;&gt; host %s at port %d is down&quot;,<br>
&gt;&gt;&gt; -                                                  i,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;  bkinfo-&gt;backend_hostname,<br>
&gt;&gt;&gt; -                                                  bkinfo-&gt;backend_port);<br>
&gt;&gt;&gt; -                               return i+1;<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       discard_persistent_db_connection(slot);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return 0;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * check if we can connect to the SystemDB<br>
&gt;&gt;&gt; - * returns 0 for OK. otherwise returns -1<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int<br>
&gt;&gt;&gt; -system_db_health_check(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int fd;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* V2 startup packet */<br>
&gt;&gt;&gt; -       typedef struct {<br>
&gt;&gt;&gt; -               int len;                /* startup packet length */<br>
&gt;&gt;&gt; -               StartupPacket_v2 sp;<br>
&gt;&gt;&gt; -       } MySp;<br>
&gt;&gt;&gt; -       MySp mysp;<br>
&gt;&gt;&gt; -       char kind;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       memset(&amp;mysp, 0, sizeof(mysp));<br>
&gt;&gt;&gt; -       mysp.len = htonl(296);<br>
&gt;&gt;&gt; -       mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 &lt;&lt; 16);<br>
&gt;&gt;&gt; -       strcpy(mysp.sp.database, &quot;template1&quot;);<br>
&gt;&gt;&gt; -       strncpy(mysp.sp.user, SYSDB_INFO-&gt;user, sizeof(mysp.sp.user) - 1);<br>
&gt;&gt;&gt; -       *mysp.sp.options = &#39;\0&#39;;<br>
&gt;&gt;&gt; -       *mysp.sp.unused = &#39;\0&#39;;<br>
&gt;&gt;&gt; -       *mysp.sp.tty = &#39;\0&#39;;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_debug(&quot;health_check: SystemDB status: %d&quot;, SYSDB_STATUS);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* if SystemDB is already down, ignore */<br>
&gt;&gt;&gt; -       if (SYSDB_STATUS == CON_UNUSED || SYSDB_STATUS == CON_DOWN)<br>
&gt;&gt;&gt; -               return 0;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (*SYSDB_INFO-&gt;hostname == &#39;/&#39;)<br>
&gt;&gt;&gt; -               fd = connect_unix_domain_socket_by_port(SYSDB_INFO-&gt;port,<br>
&gt;&gt;&gt; SYSDB_INFO-&gt;hostname, FALSE);<br>
&gt;&gt;&gt; -       else<br>
&gt;&gt;&gt; -               fd =<br>
&gt;&gt;&gt; connect_inet_domain_socket_by_port(SYSDB_INFO-&gt;hostname, SYSDB_INFO-&gt;port,<br>
&gt;&gt;&gt; FALSE);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (fd &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;health check failed. SystemDB host %s at port<br>
&gt;&gt;&gt; %d is down&quot;,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;hostname,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;port);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (write(fd, &amp;mysp, sizeof(mysp)) &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;health check failed during write. SystemDB<br>
&gt;&gt;&gt; host %s at port %d is down&quot;,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;hostname,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;port);<br>
&gt;&gt;&gt; -               close(fd);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       read(fd, &amp;kind, 1);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (write(fd, &quot;X&quot;, 1) &lt; 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;health check failed during write. SystemDB<br>
&gt;&gt;&gt; host %s at port %d is down&quot;,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;hostname,<br>
&gt;&gt;&gt; -                                  SYSDB_INFO-&gt;port);<br>
&gt;&gt;&gt; -               close(fd);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       close(fd);<br>
&gt;&gt;&gt; -       return 0;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * handle SIGCHLD<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static RETSIGTYPE reap_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -       sigchld_request = 1;<br>
&gt;&gt;&gt; -       write(pipe_fds[1], &quot;\0&quot;, 1);<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * Attach zombie processes and restart child processes.<br>
&gt;&gt;&gt; - * reaper() must be called protected from signals.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static void reaper(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t pid;<br>
&gt;&gt;&gt; -       int status;<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_debug(&quot;reap_handler called&quot;);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (exiting)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;reap_handler: exited due to exiting&quot;);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (switching)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;reap_handler: exited due to switching&quot;);<br>
&gt;&gt;&gt; -               return;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* clear SIGCHLD request */<br>
&gt;&gt;&gt; -       sigchld_request = 0;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -#ifdef HAVE_WAITPID<br>
&gt;&gt;&gt; -       pool_debug(&quot;reap_handler: call waitpid&quot;);<br>
&gt;&gt;&gt; -       while ((pid = waitpid(-1, &amp;status, WNOHANG)) &gt; 0)<br>
&gt;&gt;&gt; -#else<br>
&gt;&gt;&gt; -       pool_debug(&quot;reap_handler: call wait3&quot;);<br>
&gt;&gt;&gt; -       while ((pid = wait3(&amp;status, WNOHANG, NULL)) &gt; 0)<br>
&gt;&gt;&gt; -#endif<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (WIFSIGNALED(status) &amp;&amp; WTERMSIG(status) == SIGSEGV)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       /* Child terminated by segmentation fault. Report<br>
&gt;&gt;&gt; it */<br>
&gt;&gt;&gt; -                       pool_error(&quot;Child process %d was terminated by<br>
&gt;&gt;&gt; segmentation fault&quot;, pid);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* if exiting child process was PCP handler */<br>
&gt;&gt;&gt; -               if (pid == pcp_pid)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (WIFSIGNALED(status))<br>
&gt;&gt;&gt; -                               pool_log(&quot;PCP child %d exits with status<br>
&gt;&gt;&gt; %d by signal %d&quot;, pid, status, WTERMSIG(status));<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                               pool_log(&quot;PCP child %d exits with status<br>
&gt;&gt;&gt; %d&quot;, pid, status);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       pcp_pid = pcp_fork_a_child(pcp_unix_fd,<br>
&gt;&gt;&gt; pcp_inet_fd, pcp_conf_file);<br>
&gt;&gt;&gt; -                       pool_log(&quot;fork a new PCP child pid %d&quot;, pcp_pid);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* exiting process was worker process */<br>
&gt;&gt;&gt; -               else if (pid == worker_pid)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (WIFSIGNALED(status))<br>
&gt;&gt;&gt; -                               pool_log(&quot;worker child %d exits with<br>
&gt;&gt;&gt; status %d by signal %d&quot;, pid, status, WTERMSIG(status));<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                               pool_log(&quot;worker child %d exits with<br>
&gt;&gt;&gt; status %d&quot;, pid, status);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       if (status)<br>
&gt;&gt;&gt; -                               worker_pid = worker_fork_a_child();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       pool_log(&quot;fork a new worker child pid %d&quot;,<br>
&gt;&gt;&gt; worker_pid);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /* exiting process was watchdog process */<br>
&gt;&gt;&gt; -               else if (pool_config-&gt;use_watchdog &amp;&amp;<br>
&gt;&gt;&gt; wd_is_watchdog_pid(pid))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (!wd_reaper_watchdog(pid, status))<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               pool_error(&quot;wd_reaper failed&quot;);<br>
&gt;&gt;&gt; -                               myexit(1);<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (WIFSIGNALED(status))<br>
&gt;&gt;&gt; -                               pool_debug(&quot;child %d exits with status %d<br>
&gt;&gt;&gt; by signal %d&quot;, pid, status, WTERMSIG(status));<br>
&gt;&gt;&gt; -                       else<br>
&gt;&gt;&gt; -                               pool_debug(&quot;child %d exits with status<br>
&gt;&gt;&gt; %d&quot;, pid, status);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                       /* look for exiting child&#39;s pid */<br>
&gt;&gt;&gt; -                       for (i=0;i&lt;pool_config-&gt;num_init_children;i++)<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               if (pid == process_info[i].pid)<br>
&gt;&gt;&gt; -                               {<br>
&gt;&gt;&gt; -                                       /* if found, fork a new child */<br>
&gt;&gt;&gt; -                                       if (!switching &amp;&amp; !exiting &amp;&amp;<br>
&gt;&gt;&gt; status)<br>
&gt;&gt;&gt; -                                       {<br>
&gt;&gt;&gt; -                                               process_info[i].pid =<br>
&gt;&gt;&gt; fork_a_child(unix_fd, inet_fd, i);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; process_info[i].start_time = time(NULL);<br>
&gt;&gt;&gt; -                                               pool_debug(&quot;fork a new<br>
&gt;&gt;&gt; child pid %d&quot;, process_info[i].pid);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -                                       }<br>
&gt;&gt;&gt; -                               }<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       pool_debug(&quot;reap_handler: normally exited&quot;);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get node information specified by node_number<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -BackendInfo *<br>
&gt;&gt;&gt; -pool_get_node_info(int node_number)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       if (node_number &lt; 0 || node_number &gt;= NUM_BACKENDS)<br>
&gt;&gt;&gt; -               return NULL;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return &amp;BACKEND_INFO(node_number);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get number of nodes<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -int<br>
&gt;&gt;&gt; -pool_get_node_count(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       return NUM_BACKENDS;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get process ids<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -int *<br>
&gt;&gt;&gt; -pool_get_process_list(int *array_size)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int        *array;<br>
&gt;&gt;&gt; -       int             i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       *array_size = pool_config-&gt;num_init_children;<br>
&gt;&gt;&gt; -       array = calloc(*array_size, sizeof(int));<br>
&gt;&gt;&gt; -       for (i = 0; i &lt; *array_size; i++)<br>
&gt;&gt;&gt; -               array[i] = process_info[i].pid;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return array;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get process information specified by pid<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -ProcessInfo *<br>
&gt;&gt;&gt; -pool_get_process_info(pid_t pid)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int             i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for (i = 0; i &lt; pool_config-&gt;num_init_children; i++)<br>
&gt;&gt;&gt; -               if (process_info[i].pid == pid)<br>
&gt;&gt;&gt; -                       return &amp;process_info[i];<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return NULL;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get System DB information<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -SystemDBInfo *<br>
&gt;&gt;&gt; -pool_get_system_db_info(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       if (system_db_info == NULL)<br>
&gt;&gt;&gt; -               return NULL;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return system_db_info-&gt;info;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * handle SIGUSR2<br>
&gt;&gt;&gt; - * Wakeup all processes<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static void wakeup_children(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       kill_all_children(SIGUSR2);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static RETSIGTYPE wakeup_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -       wakeup_request = 1;<br>
&gt;&gt;&gt; -       write(pipe_fds[1], &quot;\0&quot;, 1);<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * handle SIGHUP<br>
&gt;&gt;&gt; - *<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static RETSIGTYPE reload_config_handler(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -       reload_config_request = 1;<br>
&gt;&gt;&gt; -       write(pipe_fds[1], &quot;\0&quot;, 1);<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static void reload_config(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pool_log(&quot;reload config files.&quot;);<br>
&gt;&gt;&gt; -       pool_get_config(conf_file, RELOAD_CONFIG);<br>
&gt;&gt;&gt; -       if (pool_config-&gt;enable_pool_hba)<br>
&gt;&gt;&gt; -               load_hba(hba_file);<br>
&gt;&gt;&gt; -       if (pool_config-&gt;parallel_mode)<br>
&gt;&gt;&gt; -               pool_memset_system_db_info(system_db_info-&gt;info);<br>
&gt;&gt;&gt; -       kill_all_children(SIGHUP);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (worker_pid)<br>
&gt;&gt;&gt; -               kill(worker_pid, SIGHUP);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static void kill_all_children(int sig)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* kill all children */<br>
&gt;&gt;&gt; -       for (i = 0; i &lt; pool_config-&gt;num_init_children; i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pid_t pid = process_info[i].pid;<br>
&gt;&gt;&gt; -               if (pid)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       kill(pid, sig);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* make PCP process reload as well */<br>
&gt;&gt;&gt; -       if (sig == SIGHUP)<br>
&gt;&gt;&gt; -               kill(pcp_pid, sig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * pause in a period specified by timeout. If any data is coming<br>
&gt;&gt;&gt; - * through pipe_fds[0], that means one of: failover request(SIGUSR1),<br>
&gt;&gt;&gt; - * SIGCHLD received, children wake up request(SIGUSR2 used in on line<br>
&gt;&gt;&gt; - * recovery processing) or config file reload request(SIGHUP) has been<br>
&gt;&gt;&gt; - * occurred.  In this case this function returns 1.<br>
&gt;&gt;&gt; - * otherwise 0: (no signal event occurred), -1: (error)<br>
&gt;&gt;&gt; - * XXX: is it OK that select(2) error is ignored here?<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int pool_pause(struct timeval *timeout)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       fd_set rfds;<br>
&gt;&gt;&gt; -       int n;<br>
&gt;&gt;&gt; -       char dummy;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       FD_ZERO(&amp;rfds);<br>
&gt;&gt;&gt; -       FD_SET(pipe_fds[0], &amp;rfds);<br>
&gt;&gt;&gt; -       n = select(pipe_fds[0]+1, &amp;rfds, NULL, NULL, timeout);<br>
&gt;&gt;&gt; -       if (n == 1)<br>
&gt;&gt;&gt; -               read(pipe_fds[0], &amp;dummy, 1);<br>
&gt;&gt;&gt; -       return n;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * sleep for seconds specified by &quot;second&quot;.  Unlike pool_pause(), this<br>
&gt;&gt;&gt; - * function guarantees that it will sleep for specified seconds.  This<br>
&gt;&gt;&gt; - * function uses pool_pause() internally. If it informs that there is<br>
&gt;&gt;&gt; - * a pending signal event, they are processed using CHECK_REQUEST<br>
&gt;&gt;&gt; - * macro. Note that most of these processes are done while all signals<br>
&gt;&gt;&gt; - * are blocked.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -void pool_sleep(unsigned int second)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       struct timeval current_time, sleep_time;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       gettimeofday(&amp;current_time, NULL);<br>
&gt;&gt;&gt; -       sleep_time.tv_sec = second + current_time.tv_sec;<br>
&gt;&gt;&gt; -       sleep_time.tv_usec = current_time.tv_usec;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -       while (sleep_time.tv_sec &gt; current_time.tv_sec)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               struct timeval timeout;<br>
&gt;&gt;&gt; -               int r;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               timeout.tv_sec = sleep_time.tv_sec - current_time.tv_sec;<br>
&gt;&gt;&gt; -               timeout.tv_usec = sleep_time.tv_usec -<br>
&gt;&gt;&gt; current_time.tv_usec;<br>
&gt;&gt;&gt; -               if (timeout.tv_usec &lt; 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       timeout.tv_sec--;<br>
&gt;&gt;&gt; -                       timeout.tv_usec += 1000000;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               r = pool_pause(&amp;timeout);<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -               if (r &gt; 0)<br>
&gt;&gt;&gt; -                       CHECK_REQUEST;<br>
&gt;&gt;&gt; -               POOL_SETMASK(&amp;UnBlockSig);<br>
&gt;&gt;&gt; -               gettimeofday(&amp;current_time, NULL);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       POOL_SETMASK(&amp;BlockSig);<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get_config_file_name: return full path of pgpool.conf.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -char *get_config_file_name(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       return conf_file;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * get_config_file_name: return full path of pool_hba.conf.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -char *get_hba_file_name(void)<br>
&gt;&gt;&gt; + * get_config_file_name: return full path of pool_hba.conf.<br>
&gt;&gt;&gt; + */<br>
&gt;&gt;&gt; +char *get_hba_file_name(void)<br>
&gt;&gt;&gt;  {<br>
&gt;&gt;&gt;         return hba_file;<br>
&gt;&gt;&gt;  }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * trigger_failover_command: execute specified command at failover.<br>
&gt;&gt;&gt; - *                           command_line is null-terminated string.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int trigger_failover_command(int node, const char *command_line,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; int old_master, int new_master, int old_primary)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       int r = 0;<br>
&gt;&gt;&gt; -       String *exec_cmd;<br>
&gt;&gt;&gt; -       char port_buf[6];<br>
&gt;&gt;&gt; -       char buf[2];<br>
&gt;&gt;&gt; -       BackendInfo *info;<br>
&gt;&gt;&gt; -       BackendInfo *newmaster;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (command_line == NULL || (strlen(command_line) == 0))<br>
&gt;&gt;&gt; -               return 0;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* check failed nodeID */<br>
&gt;&gt;&gt; -       if (node &lt; 0 || node &gt; NUM_BACKENDS)<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       info = pool_get_node_info(node);<br>
&gt;&gt;&gt; -       if (!info)<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       buf[1] = &#39;\0&#39;;<br>
&gt;&gt;&gt; -       pool_memory = pool_memory_create(PREPARE_BLOCK_SIZE);<br>
&gt;&gt;&gt; -       if (!pool_memory)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;trigger_failover_command:<br>
&gt;&gt;&gt; pool_memory_create() failed&quot;);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       exec_cmd = init_string(&quot;&quot;);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       while (*command_line)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (*command_line == &#39;%&#39;)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       if (*(command_line + 1))<br>
&gt;&gt;&gt; -                       {<br>
&gt;&gt;&gt; -                               char val = *(command_line + 1);<br>
&gt;&gt;&gt; -                               switch (val)<br>
&gt;&gt;&gt; -                               {<br>
&gt;&gt;&gt; -                                       case &#39;p&#39;: /* failed node port */<br>
&gt;&gt;&gt; -                                               snprintf(port_buf,<br>
&gt;&gt;&gt; sizeof(port_buf), &quot;%d&quot;, info-&gt;backend_port);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;D&#39;: /* failed node database<br>
&gt;&gt;&gt; directory */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, info-&gt;backend_data_directory);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;d&#39;: /* failed node id */<br>
&gt;&gt;&gt; -                                               snprintf(port_buf,<br>
&gt;&gt;&gt; sizeof(port_buf), &quot;%d&quot;, node);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;h&#39;: /* failed host name */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, info-&gt;backend_hostname);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;H&#39;: /* new master host name<br>
&gt;&gt;&gt; */<br>
&gt;&gt;&gt; -                                               newmaster =<br>
&gt;&gt;&gt; pool_get_node_info(new_master);<br>
&gt;&gt;&gt; -                                               if (newmaster)<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, newmaster-&gt;backend_hostname);<br>
&gt;&gt;&gt; -                                               else<br>
&gt;&gt;&gt; -                                                       /* no valid new<br>
&gt;&gt;&gt; master */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, &quot;&quot;);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;m&#39;: /* new master node id */<br>
&gt;&gt;&gt; -                                               snprintf(port_buf,<br>
&gt;&gt;&gt; sizeof(port_buf), &quot;%d&quot;, new_master);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;r&#39;: /* new master port */<br>
&gt;&gt;&gt; -                                               newmaster =<br>
&gt;&gt;&gt; pool_get_node_info(get_next_master_node());<br>
&gt;&gt;&gt; -                                               if (newmaster)<br>
&gt;&gt;&gt; -                                               {<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; snprintf(port_buf, sizeof(port_buf), &quot;%d&quot;, newmaster-&gt;backend_port);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               }<br>
&gt;&gt;&gt; -                                               else<br>
&gt;&gt;&gt; -                                                       /* no valid new<br>
&gt;&gt;&gt; master */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, &quot;&quot;);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;R&#39;: /* new master database<br>
&gt;&gt;&gt; directory */<br>
&gt;&gt;&gt; -                                               newmaster =<br>
&gt;&gt;&gt; pool_get_node_info(get_next_master_node());<br>
&gt;&gt;&gt; -                                               if (newmaster)<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, newmaster-&gt;backend_data_directory);<br>
&gt;&gt;&gt; -                                               else<br>
&gt;&gt;&gt; -                                                       /* no valid new<br>
&gt;&gt;&gt; master */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, &quot;&quot;);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;M&#39;: /* old master node id */<br>
&gt;&gt;&gt; -                                               snprintf(port_buf,<br>
&gt;&gt;&gt; sizeof(port_buf), &quot;%d&quot;, old_master);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;P&#39;: /* old primary node id<br>
&gt;&gt;&gt; */<br>
&gt;&gt;&gt; -                                               snprintf(port_buf,<br>
&gt;&gt;&gt; sizeof(port_buf), &quot;%d&quot;, old_primary);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, port_buf);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       case &#39;%&#39;: /* escape */<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; string_append_char(exec_cmd, &quot;%&quot;);<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -                                       default: /* ignore */<br>
&gt;&gt;&gt; -                                               break;<br>
&gt;&gt;&gt; -                               }<br>
&gt;&gt;&gt; -                               command_line++;<br>
&gt;&gt;&gt; -                       }<br>
&gt;&gt;&gt; -               } else {<br>
&gt;&gt;&gt; -                       buf[0] = *command_line;<br>
&gt;&gt;&gt; -                       string_append_char(exec_cmd, buf);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               command_line++;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (strlen(exec_cmd-&gt;data) != 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;execute command: %s&quot;, exec_cmd-&gt;data);<br>
&gt;&gt;&gt; -               r = system(exec_cmd-&gt;data);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_memory_delete(pool_memory, 0);<br>
&gt;&gt;&gt; -       pool_memory = NULL;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       return r;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; - * Find the primary node (i.e. not standby node) and returns its node<br>
&gt;&gt;&gt; - * id. If no primary node is found, returns -1.<br>
&gt;&gt;&gt; - */<br>
&gt;&gt;&gt; -static int find_primary_node(void)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       BackendInfo *bkinfo;<br>
&gt;&gt;&gt; -       POOL_CONNECTION_POOL_SLOT *s;<br>
&gt;&gt;&gt; -       POOL_CONNECTION *con;<br>
&gt;&gt;&gt; -       POOL_STATUS status;<br>
&gt;&gt;&gt; -       POOL_SELECT_RESULT *res;<br>
&gt;&gt;&gt; -       bool is_standby;<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* Streaming replication mode? */<br>
&gt;&gt;&gt; -       if (pool_config-&gt;master_slave_mode == 0 ||<br>
&gt;&gt;&gt; -               strcmp(pool_config-&gt;master_slave_sub_mode,<br>
&gt;&gt;&gt; MODE_STREAMREP))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* No point to look for primary node if not in streaming<br>
&gt;&gt;&gt; -                * replication mode.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               pool_debug(&quot;find_primary_node: not in streaming<br>
&gt;&gt;&gt; replication mode&quot;);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       for(i=0;i&lt;NUM_BACKENDS;i++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               if (!VALID_BACKEND(i))<br>
&gt;&gt;&gt; -                       continue;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /*<br>
&gt;&gt;&gt; -                * Check to see if this is a standby node or not.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               is_standby = false;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               bkinfo = pool_get_node_info(i);<br>
&gt;&gt;&gt; -               s =<br>
&gt;&gt;&gt; make_persistent_db_connection(bkinfo-&gt;backend_hostname,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;         bkinfo-&gt;backend_port,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;         &quot;postgres&quot;,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;         pool_config-&gt;sr_check_user,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;         pool_config-&gt;sr_check_password, true);<br>
&gt;&gt;&gt; -               if (!s)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_error(&quot;find_primary_node:<br>
&gt;&gt;&gt; make_persistent_connection failed&quot;);<br>
&gt;&gt;&gt; -                       return -1;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               con = s-&gt;con;<br>
&gt;&gt;&gt; -               status = do_query(con, &quot;SELECT pg_is_in_recovery()&quot;,<br>
&gt;&gt;&gt; -                                                 &amp;res, PROTO_MAJOR_V3);<br>
&gt;&gt;&gt; -               if (res-&gt;numrows &lt;= 0)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;find_primary_node: do_query returns no<br>
&gt;&gt;&gt; rows&quot;);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               if (res-&gt;data[0] == NULL)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;find_primary_node: do_query returns no<br>
&gt;&gt;&gt; data&quot;);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               if (res-&gt;nullflags[0] == -1)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_log(&quot;find_primary_node: do_query returns<br>
&gt;&gt;&gt; NULL&quot;);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               if (res-&gt;data[0] &amp;&amp; !strcmp(res-&gt;data[0], &quot;t&quot;))<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       is_standby = true;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               free_select_result(res);<br>
&gt;&gt;&gt; -               discard_persistent_db_connection(s);<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -               /*<br>
&gt;&gt;&gt; -                * If this is a standby, we continue to look for primary<br>
&gt;&gt;&gt; node.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               if (is_standby)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       pool_debug(&quot;find_primary_node: %d node is<br>
&gt;&gt;&gt; standby&quot;, i);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               else<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       break;<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (i == NUM_BACKENDS)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_debug(&quot;find_primary_node: no primary node found&quot;);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pool_log(&quot;find_primary_node: primary node id is %d&quot;, i);<br>
&gt;&gt;&gt; -       return i;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -static int find_primary_node_repeatedly(void)<br>
&gt;&gt;&gt; +/* Call back function to unlink the file */<br>
&gt;&gt;&gt; +/* Call back function to unlink the file */<br>
&gt;&gt;&gt; +static void FileUnlink(int code, Datum path)<br>
&gt;&gt;&gt;  {<br>
&gt;&gt;&gt; -       int sec;<br>
&gt;&gt;&gt; -       int node_id = -1;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /* Streaming replication mode? */<br>
&gt;&gt;&gt; -       if (pool_config-&gt;master_slave_mode == 0 ||<br>
&gt;&gt;&gt; -               strcmp(pool_config-&gt;master_slave_sub_mode,<br>
&gt;&gt;&gt; MODE_STREAMREP))<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               /* No point to look for primary node if not in streaming<br>
&gt;&gt;&gt; -                * replication mode.<br>
&gt;&gt;&gt; -                */<br>
&gt;&gt;&gt; -               pool_debug(&quot;find_primary_node: not in streaming<br>
&gt;&gt;&gt; replication mode&quot;);<br>
&gt;&gt;&gt; -               return -1;<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       /*<br>
&gt;&gt;&gt; -        * Try to find the new primary node and keep trying for<br>
&gt;&gt;&gt; -        * search_primary_node_timeout seconds.<br>
&gt;&gt;&gt; -        * search_primary_node_timeout = 0 means never timeout and keep<br>
&gt;&gt;&gt; searching<br>
&gt;&gt;&gt; -        * indefinitely<br>
&gt;&gt;&gt; +       char* filePath = (char*)path;<br>
&gt;&gt;&gt; +       if (unlink(filePath) == 0) return;<br>
&gt;&gt;&gt; +       /*<br>
&gt;&gt;&gt; +        * We are already exiting the system just produce a log entry to<br>
&gt;&gt;&gt; report an error<br>
&gt;&gt;&gt;          */<br>
&gt;&gt;&gt; -       pool_log(&quot;find_primary_node_repeatedly: waiting for finding a<br>
&gt;&gt;&gt; primary node&quot;);<br>
&gt;&gt;&gt; -       for (sec = 0; (pool_config-&gt;search_primary_node_timeout == 0 ||<br>
&gt;&gt;&gt; -                               sec &lt;<br>
&gt;&gt;&gt; pool_config-&gt;search_primary_node_timeout); sec++)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               node_id = find_primary_node();<br>
&gt;&gt;&gt; -               if (node_id != -1)<br>
&gt;&gt;&gt; -                       break;<br>
&gt;&gt;&gt; -               pool_sleep(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return node_id;<br>
&gt;&gt;&gt; -}<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -/*<br>
&gt;&gt;&gt; -* fork a follow child<br>
&gt;&gt;&gt; -*/<br>
&gt;&gt;&gt; -pid_t fork_follow_child(int old_master, int new_primary, int old_primary)<br>
&gt;&gt;&gt; -{<br>
&gt;&gt;&gt; -       pid_t pid;<br>
&gt;&gt;&gt; -       int i;<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       pid = fork();<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt; -       if (pid == 0)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_log(&quot;start triggering follow command.&quot;);<br>
&gt;&gt;&gt; -               for (i = 0; i &lt; pool_config-&gt;backend_desc-&gt;num_backends;<br>
&gt;&gt;&gt; i++)<br>
&gt;&gt;&gt; -               {<br>
&gt;&gt;&gt; -                       BackendInfo *bkinfo;<br>
&gt;&gt;&gt; -                       bkinfo = pool_get_node_info(i);<br>
&gt;&gt;&gt; -                       if (bkinfo-&gt;backend_status == CON_DOWN)<br>
&gt;&gt;&gt; -                               trigger_failover_command(i,<br>
&gt;&gt;&gt; pool_config-&gt;follow_master_command,<br>
&gt;&gt;&gt; -<br>
&gt;&gt;&gt;        old_master, new_primary, old_primary);<br>
&gt;&gt;&gt; -               }<br>
&gt;&gt;&gt; -               exit(0);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       else if (pid == -1)<br>
&gt;&gt;&gt; -       {<br>
&gt;&gt;&gt; -               pool_error(&quot;follow fork() failed. reason: %s&quot;,<br>
&gt;&gt;&gt; strerror(errno));<br>
&gt;&gt;&gt; -               exit(1);<br>
&gt;&gt;&gt; -       }<br>
&gt;&gt;&gt; -       return pid;<br>
&gt;&gt;&gt; +       ereport(LOG,<br>
&gt;&gt;&gt; +               (errmsg(&quot;unlink failed for file at path \&quot;%s\&quot;&quot;,<br>
&gt;&gt;&gt; filePath),<br>
&gt;&gt;&gt; +                       errdetail(&quot;\&quot;%s\&quot;&quot;, strerror(errno))));<br>
&gt;&gt;&gt;  }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ...<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; [Message clipped]<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; --<br>
&gt;&gt; Ahsan Hadi<br>
&gt;&gt; Snr Director Product Development<br>
&gt;&gt; EnterpriseDB Corporation<br>
&gt;&gt; The Enterprise Postgres Company<br>
&gt;&gt;<br>
&gt;&gt; Phone: +92-51-8358874<br>
&gt;&gt; Mobile: +92-333-5162114<br>
&gt;&gt;<br>
&gt;&gt; Website: <a href="http://www.enterprisedb.com" target="_blank">www.enterprisedb.com</a><br>
&gt;&gt; EnterpriseDB Blog: <a href="http://blogs.enterprisedb.com/" target="_blank">http://blogs.enterprisedb.com/</a><br>
&gt;&gt; Follow us on Twitter: <a href="http://www.twitter.com/enterprisedb" target="_blank">http://www.twitter.com/enterprisedb</a><br>
&gt;&gt;<br>
&gt;&gt; This e-mail message (and any attachment) is intended for the use of the<br>
&gt;&gt; individual or entity to whom it is addressed. This message contains<br>
&gt;&gt; information from EnterpriseDB Corporation that may be privileged,<br>
&gt;&gt; confidential, or exempt from disclosure under applicable law. If you are<br>
&gt;&gt; not the intended recipient or authorized to receive this for the intended<br>
&gt;&gt; recipient, any use, dissemination, distribution, retention, archiving, or<br>
&gt;&gt; copying of this communication is strictly prohibited. If you have received<br>
&gt;&gt; this e-mail in error, please notify the sender immediately by reply e-mail<br>
&gt;&gt; and delete this message.<br>
&gt;&gt;<br>
</div></div></blockquote></div><br></div>