View Issue Details

IDProjectCategoryView StatusLast Update
0000282Pgpool-IIBugpublic2017-03-26 16:21
ReporterjakubsAssigned Tot-ishii 
PriorityhighSeveritymajorReproducibilityalways
Status resolvedResolutionopen 
Product Version3.6.1 
Target VersionFixed in Version 
Summary0000282: Pgpool hangs on query and doesn't send it to backend
DescriptionHi.
I have a certain piece of code in my application. It sends two queries to pgpool working in load balancer setting. I had two backends (master and slave in streaming replication mode), but the problem doesn't seem to concern that, because I am able to reproduce it only on working master.
The problem wasn't reproducing itself always in the previous version (3.6.0) and I postponed it's resolution. I wanted to resolve it today, so I installed newest version of pgpool. And now I am able reproduce this problem every time.
My setup is:
OS: CentOS 7 3.10.0-327.36.3.el7.x86_64
DB: PostgreSQL 9.6
pgPool-II: version 3.6.1

The problem seems to occur every time I try when it is on the same db connection (though I'm not sure about it, but I made setup which opens one connection and it reproduces everytime. However when I made performance tests with hundreds of clients and dozens of connections it didn't occur so often). I will attach some logs:
1. Log from pgpool with debug mode on and sequence of queries which lead to hangup
2. Network traffick from the same time from between web server (tomcat) and pgpool
3. Network traffick from the same time from between pgpool and PostgreSQL
Network traffic files are readable by Wireshark.
You can see there that tomcat queries pgpool for some objects, pgpool receives it, logs making a query of form:

SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = to_regclass('"pt_trace_types"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'

but it doesn't actually send it to backend (no such query in second network trafic log). And this is it, tomcat waits for query to return but pgpool doesn't make it.

I sam a similar bug no. 167, maybe it is linked somehow.
Please let me know if you need any more logs or information.
TagsNo tags attached.

Activities

jakubs

2017-01-30 22:55

reporter  

pgpoolLog.txt (6,733 bytes)
Jan 30 14:21:46 bosch pgpool[3625]: [269-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: B message
Jan 30 14:21:46 bosch pgpool[3625]: [270-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: Execute: SELECT '1'
Jan 30 14:21:46 bosch pgpool[3625]: [271-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: bind <unnamed> to S_1
Jan 30 14:21:46 bosch pgpool[3625]: [272-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: StartTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [273-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: StartTransaction
Jan 30 14:21:46 bosch pgpool[3625]: [274-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: name: unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
Jan 30 14:21:46 bosch pgpool[3625]: [275-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: LOG: execute S_1: SELECT '1'
Jan 30 14:21:46 bosch pgpool[3625]: [276-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: CommitTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [277-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: CommitTransaction
Jan 30 14:21:46 bosch pgpool[3625]: [278-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
Jan 30 14:21:46 bosch pgpool[3625]: [279-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: Parse: BEGIN
Jan 30 14:21:46 bosch pgpool[3625]: [280-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: B message
Jan 30 14:21:46 bosch pgpool[3625]: [281-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: Execute: BEGIN
Jan 30 14:21:46 bosch pgpool[3625]: [282-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: parse <unnamed>: BEGIN
Jan 30 14:21:46 bosch pgpool[3625]: [283-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: StartTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [284-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: StartTransaction
Jan 30 14:21:46 bosch pgpool[3625]: [285-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: name: unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
Jan 30 14:21:46 bosch pgpool[3625]: [286-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: bind <unnamed> to <unnamed>
Jan 30 14:21:46 bosch pgpool[3625]: [287-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: LOG: execute <unnamed>: BEGIN
Jan 30 14:21:46 bosch pgpool[3625]: [288-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: ProcessUtility
Jan 30 14:21:46 bosch pgpool[3625]: [289-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: CommitTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [290-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = to_regclass('"pt_traceable_objects"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'
Jan 30 14:21:46 bosch pgpool[3625]: [291-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.relname = 'pt_traceable_objects' AND c.relnamespace = n.oid AND n.nspname ~ '^pg_temp_'
Jan 30 14:21:46 bosch pgpool[3625]: [292-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: SELECT count(*) FROM pg_catalog.pg_class AS c WHERE c.oid = to_regclass('"pt_traceable_objects"') AND c.relpersistence = 'u'
Jan 30 14:21:46 bosch pgpool[3625]: [293-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: Parse: select this_.ID as ID202_0_, this_.TRACE_VERSION as TRACE2_202_0_, this_.CODE as CODE202_0_, this_.NAME as NAME202_0_, this_.DESCRIPTION as DESCRIPT5_202_0_, this_.TRACE_CREATE_TIMESTAMP as TRACE6_202_0_, this_.TRACE_MODIFY_TIMESTAMP as TRACE7_202_0_, this_.TRACE_FLAG as TRACE8_202_0_ from PT_TRACEABLE_OBJECTS this_ where this_.TRACE_FLAG < $1 and this_.CODE=$2
Jan 30 14:21:46 bosch pgpool[3625]: [294-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: B message
Jan 30 14:21:46 bosch pgpool[3625]: [295-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: D message
Jan 30 14:21:46 bosch pgpool[3625]: [296-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: Execute: select this_.ID as ID202_0_, this_.TRACE_VERSION as TRACE2_202_0_, this_.CODE as CODE202_0_, this_.NAME as NAME202_0_, this_.DESCRIPTION as DESCRIPT5_202_0_, this_.TRACE_CREATE_TIMESTAMP as TRACE6_202_0_, this_.TRACE_MODIFY_TIMESTAMP as TRACE7_202_0_, this_.TRACE_FLAG as TRACE8_202_0_ from PT_TRACEABLE_OBJECTS this_ where this_.TRACE_FLAG < $1 and this_.CODE=$2
Jan 30 14:21:46 bosch pgpool[3625]: [297-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: parse S_3: select this_.ID as ID202_0_, this_.TRACE_VERSION as TRACE2_202_0_, this_.CODE as CODE202_0_, this_.NAME as NAME202_0_, this_.DESCRIPTION as DESCRIPT5_202_0_, this_.TRACE_CREATE_TIMESTAMP as TRACE6_202_0_, this_.TRACE_MODIFY_TIMESTAMP as TRACE7_202_0_, this_.TRACE_FLAG as TRACE8_202_0_ from PT_TRACEABLE_OBJECTS this_ where this_.TRACE_FLAG < $1 and this_.CODE=$2
Jan 30 14:21:46 bosch pgpool[3625]: [298-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: StartTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [299-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: bind C_4 to S_3
Jan 30 14:21:46 bosch pgpool[3625]: [300-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: LOG: execute S_3/C_4: select this_.ID as ID202_0_, this_.TRACE_VERSION as TRACE2_202_0_, this_.CODE as CODE202_0_, this_.NAME as NAME202_0_, this_.DESCRIPTION as DESCRIPT5_202_0_, this_.TRACE_CREATE_TIMESTAMP as TRACE6_202_0_, this_.TRACE_MODIFY_TIMESTAMP as TRACE7_202_0_, this_.TRACE_FLAG as TRACE8_202_0_ from PT_TRACEABLE_OBJECTS this_ where this_.TRACE_FLAG < $1 and this_.CODE=$2
Jan 30 14:21:46 bosch pgpool[3625]: [301-1] 2017-01-30 14:21:46: pid 3625: LOG:  backend [0]: DEBUG: CommitTransactionCommand
Jan 30 14:21:46 bosch pgpool[3625]: [302-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: C message
Jan 30 14:21:46 bosch pgpool[3625]: [303-1] 2017-01-30 14:21:46: pid 3625: LOG:  DB node id: 0 backend pid: 3692 statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = to_regclass('"pt_trace_types"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'
pgpoolLog.txt (6,733 bytes)

jakubs

2017-01-30 22:56

reporter  

hangPgPool2Postgres.pcap (16,183 bytes)

jakubs

2017-01-30 22:56

reporter  

hangTomcat2PgPool.pcap (7,793 bytes)

t-ishii

2017-02-03 14:56

developer   ~0001322

But according the pgpool log you attached, Pgpool-II actually sent the query to PostgreSQL:

LOG: DB node id: 0 backend pid: 3692 statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = to_regclass('"pt_trace_types"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'

(This is the very last line of the log file).

jakubs

2017-02-03 17:28

reporter   ~0001323

I know that log says it sent the query to backend but there is no such query on the wire as you can see in hangPgPool2Postgres.pcap file (or in the database itself - last query on the session is the one done before) so I suspected that pgpool logged the query but didn't actually send it.
It is definitely problem with pgpool because if I connect my application directly to master database there is no single hung query (and I test it with multiple users so there is loads of queries being sent), everything works as it should.

t-ishii

2017-02-03 17:33

developer   ~0001324

I haven't heard this kind of case (Pgpool-II sends a query, but it doesn't reach to PostgreSQL) since Pgpool was born. So it's hard to believe to be honest.

jakubs

2017-02-03 17:43

reporter   ~0001325

Ok. I will try to find the cause myself and let know here what was the problem.

t-ishii

2017-02-03 17:50

developer   ~0001326

One way to do this, is attaching strace and see if Pgpool-II process actually sends packet to OS. You can see this by watching write() system call.
To make the operation easier, you could set num_init_children to 1, and start Pgpool-II and the issue ps command.

21320 ? S 0:00 pgpool: wait for connection request

This is the process which handles incoming connections from clients and you want to attach strace to it.

Hope this helps.

jakubs

2017-02-16 21:48

reporter   ~0001348

Ok, so I managed finally to find time to debug pgpool code and find out what exactly is happening. As you could see in my attachment hangPgPool2Postgres.pcap, right before end of it is the sequence of messages between pgpool and Postgres:

<Z
>C
>H
<3
>H

(Postgres end is on the right side).
As you can see, pgpool issues H (Flush) after CloseComplete (3) received from Postgres. At this stage (right before H is sent to Postgres) the flag in session_context called is_pending_response is set after calling Close in ProcessFrontendResponse in pool_proto_modules.c:2422, and not unset after calling CloseComplete in ProcessBackendResponse in pool_proto_modules.c:2579. When pgpool gets next query from frontend (Parse) it tries to determine if table is catalog table. It is also first query to this table so there is no cached result and pgpool must send query

SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.oid = to_regclass('"pt_trace_types"') AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'

to Postgres to determine it. Eventually it ends up in function pool_search_relcache in pool_relcache.c in the line 165 where function do_query is called. In do_query (pool_process_query.c) in line 2012 there is an "if" checking if flag is_pending_response is set, and it is because it was never unset from the previous operation (Close and CloseCompletion). And here there is H sent to Postgres by pgpool and there is waiting for response from Postgres which never happens because there is nothing pending - the last message was CloseCompletion so there can be nothing waiting to be flushed).

Finally there is a question to you how should it be handled. I simply added call of function pool_unset_pending_response after line 2582 in pool_proto_modules.c and it does the trick for me, bu I'm new to Postgres protocol and pgpool so I think you should evaluate if it is really a bug or if there is something wrong with some other component of the test setup.

t-ishii

2017-02-23 17:03

developer   ~0001359

I have created a patch which could solve the problem.

Can you please try it out?

http://www.pgpool.net/mantisbt/file_download.php?file_id=295&type=bug

jakubs

2017-02-23 21:38

reporter   ~0001362

I tries to apply patch to source version 3.6.1 but I get an error aplying junk 0000014 at 1593 in file src/protocol/pool_proto_modules.c. The rej file is as follows:

--- src/protocol/pool_proto_modules.c
+++ src/protocol/pool_proto_modules.c
@@ -1593,12 +1638,12 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                pool_unset_pending_response();

                /*
- * Remove send message
+ * Remove sent message
                 */
                ereport(DEBUG1,
                                (errmsg("Close: removing sent message %c %s", *contents, contents+1)));
-
- pool_remove_sent_message(*contents == 'S'?'P':'B', contents+1);
+ pool_set_sent_message_state(msg);
+// pool_remove_sent_message(*contents == 'S'?'P':'B', contents+1);
        }

        return POOL_CONTINUE;


Is this the right version?

t-ishii

2017-02-24 07:49

developer   ~0001364

The patch can be applied to 3.6 stable head.

Can you please upgrade to 3.6 stable head and apply the patch?

Or apply attached patch (which is diff between 3.6.1 and 3.6 stable head as of today) before applying the patch.

t-ishii

2017-02-24 07:49

developer  

V3_6_1-V3_6_STABLE.diff (51,399 bytes)
diff --git a/doc.ja/src/sgml/release-3.1.sgml b/doc.ja/src/sgml/release-3.1.sgml
index e0e2625..e627755 100644
--- a/doc.ja/src/sgml/release-3.1.sgml
+++ b/doc.ja/src/sgml/release-3.1.sgml
@@ -38,7 +38,7 @@
 	  It was intended to keep the consistency, but there's no point in other
 	  than native replication mode.
       -->
-本来は一貫性を維持するためにキャセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャセルする必要がないので、修正しました。
+本来は一貫性を維持するためにキャンセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャンセルする必要がないので、修正しました。
 	</para>
       </listitem>
 
@@ -59,7 +59,7 @@ MD5 salt を生成するときに、<function>random()</function> を使用し
 	  store current time at the start up of Pgpool-II main process for later
 	  use.
     -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
 	</para>
       </listitem>
diff --git a/doc.ja/src/sgml/release-3.2.sgml b/doc.ja/src/sgml/release-3.2.sgml
index 60cf279..28bef4a 100644
--- a/doc.ja/src/sgml/release-3.2.sgml
+++ b/doc.ja/src/sgml/release-3.2.sgml
@@ -50,7 +50,7 @@
 	  It was intended to keep the consistency, but there's no point in other
 	  than native replication mode.
       -->
-本来は一貫性を維持するためにキャセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャセルする必要がないので、修正しました。
+本来は一貫性を維持するためにキャンセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャンセルする必要がないので、修正しました。
 	</para>
       </listitem>
 
@@ -71,7 +71,7 @@ MD5 salt を生成するときに、<function>random()</function> を使用し
 	  store current time at the start up of Pgpool-II main process for later
 	  use.
     -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
 	</para>
       </listitem>
diff --git a/doc.ja/src/sgml/release-3.3.sgml b/doc.ja/src/sgml/release-3.3.sgml
index c081456..d3b82a8 100644
--- a/doc.ja/src/sgml/release-3.3.sgml
+++ b/doc.ja/src/sgml/release-3.3.sgml
@@ -81,7 +81,7 @@ wd_authkeyは、HMAC SHA-256ハッシングを使用するようになりまし
 	  It was intended to keep the consistency, but there's no point in other
 	  than native replication mode.
       -->
-本来は一貫性を維持するためにキャセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャセルする必要がないので、修正しました。
+本来は一貫性を維持するためにキャンセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャンセルする必要がないので、修正しました。
 	</para>
       </listitem>
 
@@ -153,7 +153,7 @@ MD5 salt を生成するときに、<function>random()</function> を使用し
 	  store current time at the start up of Pgpool-II main process for later
 	  use.
     -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
 	</para>
       </listitem>
diff --git a/doc.ja/src/sgml/release-3.4.sgml b/doc.ja/src/sgml/release-3.4.sgml
index e1a5648..e991a98 100644
--- a/doc.ja/src/sgml/release-3.4.sgml
+++ b/doc.ja/src/sgml/release-3.4.sgml
@@ -169,7 +169,7 @@ MD5 salt を生成するときに、<function>random()</function> を使用し
         <function>random()</function> should not be used in security related applications.  To
         replace <function>random()</function>, import <function>PostmasterRandom()</function> from PostgreSQL.
         -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
 	</para>
       </listitem>
diff --git a/doc.ja/src/sgml/release-3.5.sgml b/doc.ja/src/sgml/release-3.5.sgml
index 57569ef..8adc370 100644
--- a/doc.ja/src/sgml/release-3.5.sgml
+++ b/doc.ja/src/sgml/release-3.5.sgml
@@ -80,7 +80,7 @@ wd_authkeyは、HMAC SHA-256ハッシングを使用するようになりまし
 	  According to the bug231, the bug seem to bite you if all of
 	  following conditions are met:
       -->
-bug 231による、以下の条件がすべて満たされていると、このバグが発生する可能性がありました。
+bug 231によると、以下の条件がすべて満たされていると、このバグが発生する可能性がありました。
 	</para>
 	<itemizedlist>
 	  <listitem>
@@ -152,7 +152,7 @@ Pgpool-IIはそれをバックエンド1に転送します。
         <!--
 	      Frontend sends Parse, Bind, Execute of COMMIT
           -->
-フロントエンドは、Parse、Bind、COMMIT の Execute を送信します。
+フロントエンドは、COMMITのParse、Bind、Executeを送信します。
 	    </para>
 	  </listitem>
 	  <listitem>
@@ -186,7 +186,7 @@ Pgpool-IIはそれをバックエンド0と1に転送します。
 	      backend 1 replies back close complete ("3") because of
 	      #3.
           -->
-バックエンド0はParse complete( "1")を返しますが、バックエンド1は#3によりcloes complete( "3")を返します。
+バックエンド0はParse complete( "1")を返しますが、バックエンド1は#3によりclose complete( "3")を返します。
 	    </para>
 	  </listitem>
 	  <listitem>
@@ -302,7 +302,7 @@ child.cには、elogを呼び出すシグナルハンドラがあります。 
 	  It was intended to keep the consistency, but there's no point in other
 	  than native replication mode.
       -->
-本来は一貫性を維持するためにキャセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャセルする必要がないので、修正しました。
+本来は一貫性を維持するためにキャンセルされるようになっていましたが、ネイティブレプリケーションモード以外の場合ではキャンセルする必要がないので、修正しました。
 	</para>
       </listitem>
 
@@ -416,7 +416,7 @@ pgpool コマンドで廃止されたオプション"-c"を削除しました。
 以前はスタンバイノードが<productname>Pgpool-II</productname>マスターノードに対して設定パラメータの値を検証し、不整合が見つかった場合にはFATALエラーが出力されていました。
 この修正で、<productname>Pgpool-II</productname>マスターノードに検証の役割が移譲されました。
 マスターノードは参加している個々のスタンバイノードの設定値をローカルの設定値と比較し、違っている場合にはエラーではなくてWARNINGメッセージを出力します。
-この方法では、watchdogクラスタとユーザは、手動でマスター<productname>Pgpool-II</productname>ログの中から不整合ワーニングを見つけて、<productname>Pgpool-II</productname>マスターのスイッチオーバが見つかった時に驚くようなことが起こらないようにしなければなりません。
+この方法では、ユーザは、手動でマスター<productname>Pgpool-II</productname>ログの中から不整合ワーニングを見つけて、<productname>Pgpool-II</productname>マスターのスイッチオーバが起きたときに驚くようなことが起こらないようにしなければなりません。
 	</para>
       </listitem>
 
@@ -448,7 +448,7 @@ MD5 salt を生成するときに、<function>random()</function> を使用し
         <function>random()</function> should not be used in security related applications.  To
         replace <function>random()</function>, import <function>PostmasterRandom()</function> from PostgreSQL.
         -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
 	</para>
       </listitem>
diff --git a/doc.ja/src/sgml/release-3.6.sgml b/doc.ja/src/sgml/release-3.6.sgml
index 319f7c9..a2f1e31 100644
--- a/doc.ja/src/sgml/release-3.6.sgml
+++ b/doc.ja/src/sgml/release-3.6.sgml
@@ -894,7 +894,7 @@ watchdogクラスタでのフェイルオーバーコマンドの転送処理が
 以前はスタンバイノードが<productname>Pgpool-II</productname>マスターノードに対して設定パラメータの値を検証し、不整合が見つかった場合にはFATALエラーが出力されていました。
 この修正で、<productname>Pgpool-II</productname>マスターノードに検証の役割が移譲されました。
 マスターノードは参加している個々のスタンバイノードの設定値をローカルの設定値と比較し、違っている場合にはエラーではなくてWARNINGメッセージを出力します。
-この方法では、watchdogクラスタとユーザは、手動でマスター<productname>Pgpool-II</productname>ログの中から不整合ワーニングを見つけて、<productname>Pgpool-II</productname>マスターのスイッチオーバが見つかった時に驚くようなことが起こらないようにしなければなりません。
+この方法では、ユーザは、手動でマスター<productname>Pgpool-II</productname>ログの中から不整合ワーニングを見つけて、<productname>Pgpool-II</productname>マスターのスイッチオーバが起きたときに驚くようなことが起こらないようにしなければなりません。
         </para>
       </listitem>
       <listitem>
@@ -935,7 +935,7 @@ watchdogクラスタでのフェイルオーバーコマンドの転送処理が
         <function>random()</function> should not be used in security related applications.  To
         replace <function>random()</function>, import <function>PostmasterRandom()</function> from PostgreSQL.
         -->
-<function>random()</function>関数はセキュリティ関連のアプリケーションに使用しないべきです。
+<function>random()</function>関数はセキュリティ関連のアプリケーションで使用すべきではありません。
 <function>random()</function>の代わりに<productname>PostgreSQL</productname>の<function>PostmasterRandom()</function> 使用するように変更しました。
         </para>
 
@@ -1854,7 +1854,7 @@ wd_authkeyは、HMAC SHA-256ハッシングを使用するようになりまし
 	  According to the bug231, the bug seem to bite you if all of
 	  following conditions are met:
       -->
-bug 231による、以下の条件がすべて満たされていると、このバグが発生する可能性がありました。
+bug 231によると、以下の条件がすべて満たされていると、このバグが発生する可能性がありました。
 	</para>
 	<itemizedlist>
 	  <listitem>
@@ -1926,7 +1926,7 @@ Pgpool-IIはそれをバックエンド1に転送します。
         <!--
 	      Frontend sends Parse, Bind, Execute of COMMIT
           -->
-フロントエンドは、Parse、Bind、COMMIT の Execute を送信します。
+フロントエンドは、COMMITのParse、Bind、Executeを送信します。
 	    </para>
 	  </listitem>
 	  <listitem>
@@ -1960,7 +1960,7 @@ Pgpool-IIはそれをバックエンド0と1に転送します。
 	      backend 1 replies back close complete ("3") because of
 	      #3.
           -->
-バックエンド0はParse complete( "1")を返しますが、バックエンド1は#3によりcloes complete( "3")を返します。
+バックエンド0はParse complete( "1")を返しますが、バックエンド1は#3によりclose complete( "3")を返します。
 	    </para>
 	  </listitem>
 	  <listitem>
diff --git a/doc/src/sgml/failover.sgml b/doc/src/sgml/failover.sgml
index fe86da2..97f81c7 100644
--- a/doc/src/sgml/failover.sgml
+++ b/doc/src/sgml/failover.sgml
@@ -82,16 +82,47 @@
           </tgroup>
         </table>
 
+	<note>
+	  <para>
+	    The "master node" referes to a node which has the
+	    "youngest (or the smallest) node id" among live the
+	    database nodes. In <link linkend="running-mode">streaming
+	    replication mode</link>, this may be different from
+	    primary node. In <xref linkend="failover-command-table">,
+	    %m is the new master node chosen
+	    by <productname>Pgpool-II</productname>. It is the node
+	    being assigned the youngest (smallest) node id which is
+	    alive. For example if you have 3 nodes, namely node 0, 1,
+	    2. Suppose node 1 the primary and all of them are healthy
+	    (no down node). If node 1 fails, failover_command is
+	    called with %m = 0.
+	  </para>
+	</note>
+
         <note>
           <para>
-            When a failover is performed, <productname>Pgpool-II</productname> kills all
-            its child processes, which will in turn terminate all the active sessions to
+            When a failover is performed,
+            basically <productname>Pgpool-II</productname> kills all
+            its child processes, which will in turn terminate all the
+            active sessions to
             <productname>Pgpool-II</productname>. After that <productname>Pgpool-II</productname>
             invokes the <command>failover_command</command> and after the command completion
             <productname>Pgpool-II</productname> starts new child processes
             which makes it ready again to accept client connections.
           </para>
+	  <para>
+	    However from <productname>Pgpool-II</productname> 3.6, In
+	    the steaming replication mode, client sessions will not be
+	    disconnected when a fail-over occurs any more if the
+	    session does not use the failed standby server. If the
+	    primary server goes down, still all sessions will be
+	    disconnected. Health check timeout case will also cause
+	    the full session disconnection. Other health check error,
+	    including retry over case does not trigger full session
+	    disconnection.
+	  </para>
         </note>
+
         <para>
           This parameter can be changed by reloading the <productname>Pgpool-II</> configurations.
         </para>
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 77facce..16f9afe 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -111,6 +111,18 @@ password: <userinput>your_password</userinput>
   <sect2 id="running-mode">
     <title>Running mode of Pgpool-II</title>
 
+    <indexterm zone="running-mode">
+      <primary>streaming replication mode</primary>
+    </indexterm>
+
+    <indexterm zone="running-mode">
+      <primary>master slave mode</primary>
+    </indexterm>
+
+    <indexterm zone="running-mode">
+      <primary>native replication mode</primary>
+    </indexterm>
+
     <para>
       There are four different running modes in <productname>Pgpool-II</>: streaming
       replication mode, master slave mode, native replication mode and
diff --git a/src/context/pool_process_context.c b/src/context/pool_process_context.c
index cfc2369..f29553a 100644
--- a/src/context/pool_process_context.c
+++ b/src/context/pool_process_context.c
@@ -52,6 +52,11 @@ void pool_init_process_context(void)
 	process_context->proc_id = my_proc_id;
 
 	process_context->local_session_id = 0;		/* initialize local session counter */
+
+	process_context->last_alarm_handler = SIG_IGN;
+	process_context->last_alarm_time = 0;
+	process_context->last_alarm_second = 0;
+	process_context->undo_alarm_second = 0;
 }
 
 /*
@@ -318,3 +323,47 @@ void pool_coninfo_unset_frontend_connected(int proc_id, int pool_index)
 		con->connected = false;
 	}
 }
+
+/*
+ * Set an alarm clock and a signal handler.
+ * For pool_alarm_undo(), the alarm second and the old handler
+ * are saved, and the remaining time is calculated.
+ */
+void pool_alarm(pool_sighandler_t handler, unsigned int second)
+{
+	POOL_PROCESS_CONTEXT *p = pool_get_process_context();
+	time_t	now = time(NULL);
+
+	alarm(second);
+	p->last_alarm_handler = pool_signal(SIGALRM, handler);
+
+	if (p->last_alarm_second)
+	{
+		p->undo_alarm_second = p->last_alarm_second - (now - p->last_alarm_time);
+		if (p->undo_alarm_second <= 0)
+		  p->undo_alarm_second = 1;
+	}
+
+	p->last_alarm_time = now;
+	p->last_alarm_second = second;
+}
+
+/*
+ * Undo the alarm signal handler using the remaining time.
+ */
+void pool_undo_alarm()
+{
+	POOL_PROCESS_CONTEXT *p = pool_get_process_context();
+
+	if (p->undo_alarm_second)
+	{
+		alarm(p->undo_alarm_second);
+		pool_signal(SIGALRM, p->last_alarm_handler);
+		p->undo_alarm_second = 0;
+	}
+	else
+	{
+		alarm(0);
+		pool_signal(SIGALRM, SIG_IGN);
+	}
+}
diff --git a/src/context/pool_query_context.c b/src/context/pool_query_context.c
index 15a5fe3..a87db43 100644
--- a/src/context/pool_query_context.c
+++ b/src/context/pool_query_context.c
@@ -88,10 +88,10 @@ void pool_query_context_destroy(POOL_QUERY_CONTEXT *query_context)
 		MemoryContext memory_context = query_context->memory_context;
 		session_context = pool_get_session_context(false);
 		pool_unset_query_in_progress();
-		if (query_context->pg_terminate_backend_conn)
+		if (!pool_is_command_success() && query_context->pg_terminate_backend_conn)
 		{
 			ereport(DEBUG1,
-				 (errmsg("resetting the connection flag for pg_terminate_backend")));
+				 (errmsg("clearing the connection flag for pg_terminate_backend")));
 			pool_unset_connection_will_be_terminated(query_context->pg_terminate_backend_conn);
 		}
 		query_context->pg_terminate_backend_conn = NULL;
diff --git a/src/context/pool_session_context.c b/src/context/pool_session_context.c
index 1060867..773ff78 100644
--- a/src/context/pool_session_context.c
+++ b/src/context/pool_session_context.c
@@ -1000,6 +1000,9 @@ void pool_set_pending_response(void)
 		ereport(ERROR,
 				(errmsg("pool_set_pending_response: session context is not initialized")));
 
+	ereport(DEBUG1,
+			(errmsg("pool_set_pending_response")));
+
 	session_context->is_pending_response = true;
 }
 
@@ -1012,6 +1015,9 @@ void pool_unset_pending_response(void)
 		ereport(ERROR,
 				(errmsg("pool_unset_pending_response: session context is not initialized")));
 
+	ereport(DEBUG1,
+			(errmsg("pool_unset_pending_response")));
+
 	session_context->is_pending_response = false;
 }
 
diff --git a/src/include/context/pool_process_context.h b/src/include/context/pool_process_context.h
index 5bdc498..caab7b1 100644
--- a/src/include/context/pool_process_context.h
+++ b/src/include/context/pool_process_context.h
@@ -46,6 +46,11 @@ typedef struct {
 
 	int local_session_id;	/* local session id */
 
+	pool_sighandler_t last_alarm_handler;
+	time_t	last_alarm_time;
+	unsigned int last_alarm_second;
+	unsigned int undo_alarm_second;
+
 } POOL_PROCESS_CONTEXT;
 
 extern void pool_init_process_context(void);
@@ -64,4 +69,7 @@ extern bool pool_is_my_coninfo(ConnectionInfo* connInfo);
 extern void pool_set_connection_will_be_terminated(ConnectionInfo* connInfo);
 extern void pool_unset_connection_will_be_terminated(ConnectionInfo* connInfo);
 
+extern void pool_alarm(pool_sighandler_t handler, unsigned int second);
+extern void pool_undo_alarm();
+
 #endif /* POOL_PROCESS_CONTEXT_H */
diff --git a/src/include/pcp/libpcp_ext.h b/src/include/pcp/libpcp_ext.h
index f58e1c9..a447dd5 100644
--- a/src/include/pcp/libpcp_ext.h
+++ b/src/include/pcp/libpcp_ext.h
@@ -101,7 +101,7 @@ typedef struct {
 							 * might be out of control of
 							 * pgpool-II. So we use "char" here.
 							 */
-	char		swallow_termination;
+	volatile char		swallow_termination;
 							/* Flag to mark that if the connection will
 							 * be terminated by the backend. it should
 							 * not be treated as a backend node failure.
diff --git a/src/include/watchdog/wd_ipc_commands.h b/src/include/watchdog/wd_ipc_commands.h
index 259ddce..bc5bd16 100644
--- a/src/include/watchdog/wd_ipc_commands.h
+++ b/src/include/watchdog/wd_ipc_commands.h
@@ -48,7 +48,12 @@ typedef struct WDIPCCmdResult
 extern void wd_ipc_initialize_data(void);
 extern char* get_watchdog_ipc_address(void);
 extern unsigned int* get_ipc_shared_key(void);
-
+extern void set_watchdog_process_needs_cleanup(void);
+extern void reset_watchdog_process_needs_cleanup(void);
+extern bool get_watchdog_process_needs_cleanup(void);
+extern void set_watchdog_node_escalated(void);
+extern void reset_watchdog_node_escalated(void);
+extern bool get_watchdog_node_escalation_state(void);
 
 extern WdCommandResult wd_start_recovery(void);
 extern WdCommandResult wd_end_recovery(void);
diff --git a/src/include/watchdog/wd_utils.h b/src/include/watchdog/wd_utils.h
index 211c838..69bdbd0 100644
--- a/src/include/watchdog/wd_utils.h
+++ b/src/include/watchdog/wd_utils.h
@@ -53,7 +53,7 @@ extern pid_t wd_issue_ping_command(char* hostname, int* outfd);
 extern List* get_all_local_ips(void);
 extern int wd_IP_up(void);
 extern int wd_IP_down(void);
-extern int wd_get_cmd(char * buf, char * cmd);
+extern char* wd_get_cmd(char* cmd);
 extern int create_monitoring_socket(void);
 extern bool read_interface_change_event(int sock, bool* link_event, bool* deleted);
 extern bool is_interface_up(struct ifaddrs *ifa);
diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c
index 56d58d0..2f7620b 100644
--- a/src/main/pgpool_main.c
+++ b/src/main/pgpool_main.c
@@ -5,7 +5,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2016	PgPool Global Development Group
+ * Copyright (c) 2003-2017	PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -805,7 +805,7 @@ static int *create_inet_domain_sockets(const char *hostname, const int port)
 			errdetail("asprintf() failed: %s", strerror(errno))));
 	}
 
-	if ((ret = getaddrinfo(hostname, portstr, &hints, &res)) != 0)
+	if ((ret = getaddrinfo((!hostname || strcmp(hostname, "*") == 0) ? NULL : hostname, portstr, &hints, &res)) != 0)
 	{
 		ereport(FATAL,
 			(errmsg("failed to create INET domain socket"),
@@ -1076,7 +1076,7 @@ static void terminate_all_childrens()
     {
 		int ret_pid;
 
-        wpid = waitpid(-1, &ret_pid, WNOHANG);
+        wpid = waitpid(-1, &ret_pid, 0);
     } while (wpid > 0 || (wpid == -1 && errno == EINTR));
 
     if (wpid == -1 && errno != ECHILD)
@@ -1449,7 +1449,7 @@ static RETSIGTYPE exit_handler(int sig)
     {
 		int ret_pid;
 
-        wpid = waitpid(-1, &ret_pid, WNOHANG);
+        wpid = waitpid(-1, &ret_pid, 0);
     } while (wpid > 0 || (wpid == -1 && errno == EINTR));
 
     if (wpid == -1 && errno != ECHILD)
@@ -1506,9 +1506,14 @@ static RETSIGTYPE failover_handler(int sig)
 
 	POOL_SETMASK(&BlockSig);
 	failover_request = 1;
+
+	write(pipe_fds[1], "\0", 1);
+
+#ifdef NOT_USED
 	if(write(pipe_fds[1], "\0", 1) < 0)
         ereport(WARNING,
                 (errmsg("failover_handler: write to pipe failed with error \"%s\"", strerror(errno))));
+#endif
 
 	POOL_SETMASK(&UnBlockSig);
 
@@ -2233,9 +2238,17 @@ static RETSIGTYPE reap_handler(int sig)
 
 	POOL_SETMASK(&BlockSig);
 	sigchld_request = 1;
+
+	if (pipe_fds[1])
+	{
+		write(pipe_fds[1], "\0", 1);
+	}
+
+#ifdef NOT_USED
 	if(pipe_fds[1] && write(pipe_fds[1], "\0", 1) < 0)
         ereport(WARNING,
             (errmsg("reap_handler: write to pipe failed with error \"%s\"", strerror(errno))));
+#endif
 
 	POOL_SETMASK(&UnBlockSig);
 
@@ -2353,6 +2366,14 @@ static void reaper(void)
 			else
 				ereport(LOG,
 						(errmsg("%s process with pid: %d exits with status %d by signal %d", exiting_process_name, pid, status, WTERMSIG(status))));
+			/* If the watchdog process was terminated abonormally.
+			 * we need to set the cleanup flag so that the new watchdog process
+			 * can start without problems
+			 */
+			if (pool_config->use_watchdog && pid == watchdog_pid)
+			{
+				set_watchdog_process_needs_cleanup();
+			}
 		}
 		else
 			ereport(LOG,
@@ -2527,9 +2548,12 @@ static RETSIGTYPE wakeup_handler(int sig)
 	if (processState != INITIALIZING)
 	{
 		POOL_SETMASK(&BlockSig);
+		write(pipe_fds[1], "\0", 1);
+#ifdef NOT_USED
 		if(write(pipe_fds[1], "\0", 1) < 0)
 			ereport(WARNING,
 				(errmsg("wakeup_handler: write to pipe failed with error \"%s\"", strerror(errno))));
+#endif
 		POOL_SETMASK(&UnBlockSig);
 	}
 	errno = save_errno;
@@ -2545,9 +2569,12 @@ static RETSIGTYPE reload_config_handler(int sig)
 
 	POOL_SETMASK(&BlockSig);
 	reload_config_request = 1;
+	write(pipe_fds[1], "\0", 1);
+#ifdef NOT_USED
 	if(write(pipe_fds[1], "\0", 1) < 0)
         ereport(WARNING,
             (errmsg("reload_config_handler: write to pipe failed with error \"%s\"", strerror(errno))));
+#endif
 
 	POOL_SETMASK(&UnBlockSig);
 
diff --git a/src/protocol/child.c b/src/protocol/child.c
index 843db92..a0f8c17 100644
--- a/src/protocol/child.c
+++ b/src/protocol/child.c
@@ -5,7 +5,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2016	PgPool Global Development Group
+ * Copyright (c) 2003-2017	PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -922,8 +922,10 @@ static RETSIGTYPE die(int sig)
 
 	save_errno = errno;
 
+#ifdef NOT_USED
 	ereport(LOG,
 			(errmsg("child process received shutdown request signal %d", sig)));
+#endif
 
 	exit_request = sig;
 
@@ -933,16 +935,20 @@ static RETSIGTYPE die(int sig)
 			/* Refuse further requests by closing listen socket */
 			if (child_inet_fd)
 			{
+#ifdef NOT_USED
 				ereport(LOG,
 						(errmsg("closing listen socket")));
+#endif
 				close(child_inet_fd);
 			}
 			close(child_unix_fd);
 
 			if (idle == 0)
 			{
+#ifdef NOT_USED
 				ereport(DEBUG1,
 						(errmsg("smart shutdown request received, but child is not in idle state")));
+#endif
 			}
 			break;
 
@@ -952,10 +958,11 @@ static RETSIGTYPE die(int sig)
 			child_exit(POOL_EXIT_NO_RESTART);
 			break;
 		default:
+#ifdef NOT_USED
 			ereport(LOG,
 				(errmsg("child process received unknown signal: %d",sig),
 					 errdetail("ignoring...")));
-
+#endif
 			break;
 	}
 
@@ -974,8 +981,10 @@ static RETSIGTYPE close_idle_connection(int sig)
 	ConnectionInfo *info;
 	int save_errno = errno;
 
+#ifdef NOT_USED
 	ereport(DEBUG1,
 			(errmsg("close connection request received")));
+#endif
 
 	for (j=0;j<pool_config->max_pool;j++, p++)
 	{
@@ -988,9 +997,12 @@ static RETSIGTYPE close_idle_connection(int sig)
 
 		if (MASTER_CONNECTION(p)->closetime > 0)		/* idle connection? */
 		{
+#ifdef NOT_USED
 			ereport(DEBUG1,
 					(errmsg("closing idle connection"),
 					 errdetail("user: %s database: %s", MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database)));
+#endif
+
 			pool_send_frontend_exits(p);
 
 			for (i=0;i<NUM_BACKENDS;i++)
@@ -1034,8 +1046,7 @@ static void enable_authentication_timeout(void)
 {
 	if(pool_config->authentication_timeout <= 0)
 		return;
-	pool_signal(SIGALRM, authentication_timeout);
-	alarm(pool_config->authentication_timeout);
+	pool_alarm(authentication_timeout, pool_config->authentication_timeout);
 	alarm_enabled = true;
 }
 
@@ -1043,8 +1054,7 @@ static void disable_authentication_timeout(void)
 {
 	if(alarm_enabled)
 	{
-		alarm(0);
-		pool_signal(SIGALRM, SIG_IGN);
+		pool_undo_alarm();
 		alarm_enabled = false;
 	}
 }
@@ -1150,8 +1160,14 @@ void child_exit(int code)
 	if(processType != PT_CHILD)
 	{
 		/* should never happen */
+
+		/* Remove call to ereport because child_exit() is called inside a
+		 * signal handler.
+		 */
+#ifdef NOT_USED
         ereport(WARNING,
                 (errmsg("child_exit: called from invalid process. ignored.")));
+#endif
 		return;
 	}
 	exit(code);
diff --git a/src/protocol/pool_connection_pool.c b/src/protocol/pool_connection_pool.c
index 537ea93..289cec4 100644
--- a/src/protocol/pool_connection_pool.c
+++ b/src/protocol/pool_connection_pool.c
@@ -353,8 +353,7 @@ void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend)
 		(errmsg("setting backend connection close timer"),
 			 errdetail("setting alarm after %d seconds", pool_config->connection_life_time)));
 
-	pool_signal(SIGALRM, pool_backend_timer_handler);
-	alarm(pool_config->connection_life_time);
+	pool_alarm(pool_backend_timer_handler, pool_config->connection_life_time);
 }
 
 /*
@@ -444,8 +443,7 @@ void pool_backend_timer(void)
 		nearest = pool_config->connection_life_time - (now - nearest);
 		if (nearest <= 0)
 		  nearest = 1;
-		pool_signal(SIGALRM, pool_backend_timer_handler);
-		alarm(nearest);
+		pool_alarm(pool_backend_timer_handler, nearest);
 	}
 
 	POOL_SETMASK(&UnBlockSig);
diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c
index d9bbca4..8f69636 100644
--- a/src/protocol/pool_proto_modules.c
+++ b/src/protocol/pool_proto_modules.c
@@ -814,6 +814,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
 			pool_set_skip_reading_from_backends();
 			pool_stats_count_up_num_cache_hits();
 			pool_unset_query_in_progress();
+			pool_unset_pending_response();
 			return POOL_CONTINUE;
 		}
 	}
@@ -900,6 +901,31 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
 #ifdef NOT_USED
 		pool_unset_query_in_progress();
 #endif
+
+		/*
+		 * Take of "writing transaction" flag.
+		 */
+		if (!is_select_query(node, query))
+		{
+			/*
+			 * If the query was not READ SELECT, and we are in an
+			 * explicit transaction, remember that we had a write
+			 * query in this transaction.
+			 */
+			if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T')
+			{
+				/* However, if the query is "SET TRANSACTION READ ONLY" or its variant,
+				 * don't set it.
+				 */
+				if (!pool_is_transaction_read_only(node))
+				{
+					ereport(DEBUG1,
+							(errmsg("not SET TRANSACTION READ ONLY")));
+
+					pool_set_writing_transaction();
+				}
+			}
+		}
 	}
 
 	return POOL_CONTINUE;
@@ -1516,6 +1542,18 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
 		pmsg = pool_pending_messages_create('C', len, contents);
 		pool_pending_message_add(pmsg);
 		pool_unset_query_in_progress();
+		/*
+		 * Remeber that we send flush or sync message to backend.
+		 */
+		pool_unset_pending_response();
+
+		/*
+		 * Remove send message
+		 */
+		ereport(DEBUG1,
+				(errmsg("Close: removing sent message %c %s", *contents, contents+1)));
+
+		pool_remove_sent_message(*contents == 'S'?'P':'B', contents+1);
 	}
 
 	return POOL_CONTINUE;
@@ -2419,7 +2457,6 @@ POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend,
 			if (!pool_is_query_in_progress() && !pool_is_ignore_till_sync())
 				pool_set_query_in_progress();
 			status = Close(frontend, backend, len, contents);
-			pool_set_pending_response();
 			break;
 
 		case 'D':	/* Describe */
diff --git a/src/redhat/pgpool.service b/src/redhat/pgpool.service
index 44ba841..2181931 100644
--- a/src/redhat/pgpool.service
+++ b/src/redhat/pgpool.service
@@ -1,10 +1,15 @@
 [Unit]
-Description=pgpool-II
+Description=Pgpool-II
 After=syslog.target network.target
 
 [Service]
+Type=forking
+
 EnvironmentFile=-/etc/sysconfig/pgpool
+
 ExecStart=/usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf $OPTS
+ExecStop=/usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf stop
+ExecReload=/usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf reload
 
 [Install]
 WantedBy=multi-user.target
diff --git a/src/test/regression/tests/068.memqcache_bug/Sample.java b/src/test/regression/tests/068.memqcache_bug/Sample.java
new file mode 100644
index 0000000..a73154b
--- /dev/null
+++ b/src/test/regression/tests/068.memqcache_bug/Sample.java
@@ -0,0 +1,50 @@
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Properties;
+
+import org.postgresql.Driver;
+
+public class Sample {
+    public Sample() {
+    }
+
+    public static void main(String[] args) throws Exception {
+        ResultSet rs;
+        Properties props = new Properties();
+        props.setProperty("user", "t-ishii");
+        props.setProperty("password", "");
+        props.setProperty("protocolVersion", "3");
+        DriverManager.setLogWriter(new PrintWriter(System.out));
+        Driver.setLogLevel(2);
+        Connection conn = DriverManager.getConnection(
+                "jdbc:postgresql://localhost:11000/test", props);
+        conn.setAutoCommit(true);
+        Statement st = conn.createStatement();
+        st.setFetchSize(100);
+	// Does not hit cache
+        rs = st.executeQuery("SELECT 1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+	// Does hit cache
+        rs = st.executeQuery("SELECT 1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+	// To call do_query()
+        rs = st.executeQuery("SELECT * FROM t1");
+        while (rs.next()) {
+            System.out.println(rs.getString(1));
+        }
+        rs.close();
+
+	conn.close();
+    }
+}
diff --git a/src/test/regression/tests/068.memqcache_bug/test.sh b/src/test/regression/tests/068.memqcache_bug/test.sh
new file mode 100755
index 0000000..273075c
--- /dev/null
+++ b/src/test/regression/tests/068.memqcache_bug/test.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+#-------------------------------------------------------------------
+# test script for a memqcache bug reported in pgpool-general-jp:1441.
+# (do_query() hangs in certain condition)
+# requires Java PostgreSQL JDBC driver.
+
+source $TESTLIBS
+TESTDIR=testdir
+export CLASSPATH=.:/usr/local/pgsql/share/postgresql-9.2-1003.jdbc4.jar
+
+rm -fr $TESTDIR
+mkdir $TESTDIR
+cd $TESTDIR
+
+# create test environment
+echo -n "creating test environment..."
+$PGPOOL_SETUP -m s -n 2 || exit 1
+echo "done."
+
+source ./bashrc.ports
+
+export PGPORT=$PGPOOL_PORT
+
+echo "memory_cache_enabled = on" >> etc/pgpool.conf
+sh startall
+wait_for_pgpool_startup
+
+cd ..
+psql test <<EOF
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(i int);
+EOF
+javac Sample.java
+java Sample	# hang here if the bug bites you...
+cd $TESTDIR
+sh shutdownall
+exit 0
+
diff --git a/src/utils/pool_shmem.c b/src/utils/pool_shmem.c
index 1b8399b..71c5a98 100644
--- a/src/utils/pool_shmem.c
+++ b/src/utils/pool_shmem.c
@@ -104,8 +104,10 @@ IpcMemoryDelete(int status, Datum shmId)
   	if (shmctl(shmId, IPC_STAT, &shmStat) < 0
   		&& (errno == EINVAL || errno == EACCES))
   		return;
+#ifdef NOT_USED
   	else if (shmStat.shm_nattch != 0)
   		return;
+#endif
 
 	if (shmctl(shmId, IPC_RMID, NULL) < 0)
 		ereport(LOG,
diff --git a/src/watchdog/watchdog.c b/src/watchdog/watchdog.c
index 418ff2c..7f02e6c 100644
--- a/src/watchdog/watchdog.c
+++ b/src/watchdog/watchdog.c
@@ -654,7 +654,7 @@ static void wd_cluster_initialize(void)
 	g_cluster.aliveNodeCount = 0;
 	g_cluster.quorum_status = -1;
 	g_cluster.nextCommandID = 1;
-	g_cluster.escalated = false;
+	g_cluster.escalated = get_watchdog_node_escalation_state();
 	g_cluster.clusterInitialized = false;
 	g_cluster.holding_vip = false;
 	g_cluster.escalation_pid = 0;
@@ -685,7 +685,16 @@ static void wd_cluster_initialize(void)
 				 errdetail("The authentication method used by pgpool-II without the SSL support is known to be weak")));
 #endif
 	}
+	if (get_watchdog_process_needs_cleanup())
+	{
+		ereport(LOG,
+				(errmsg("watchdog is recovering from the crash of watchdog process")));
 
+		/* If we are recovering from crash or abnormal termination
+		 * de-escalate the node if it was coordinator when it crashed
+		 */
+		resign_from_escalated_node();
+	}
 }
 
 static void clear_command_node_result(WDCommandNodeResult* nodeResult)
@@ -1063,7 +1072,7 @@ watchdog_main(void)
 
 	/* We can now handle ereport(ERROR) */
 	PG_exception_stack = &local_sigjmp_buf;
-
+	reset_watchdog_process_needs_cleanup();
 	/* watchdog child loop */
 	for(;;)
 	{
@@ -1129,7 +1138,7 @@ wd_create_command_server_socket(void)
 	size_t	len = 0;
 	struct sockaddr_un addr;
 	int sock = -1;
-	
+
 	/* We use unix domain stream sockets for the purpose */
 	if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
 	{
@@ -1147,6 +1156,13 @@ wd_create_command_server_socket(void)
 	ereport(INFO,
 			(errmsg("IPC socket path: \"%s\"",get_watchdog_ipc_address())));
 
+	if (get_watchdog_process_needs_cleanup())
+	{
+		/* If we are recovering from crash or abnormal termination
+		 * of watchdog process. Unlink the old socket file
+		 */
+		unlink(addr.sun_path);
+	}
 
 	if ( bind(sock, (struct sockaddr *) &addr, len) == -1)
 	{
@@ -1158,7 +1174,7 @@ wd_create_command_server_socket(void)
 				errmsg("failed to create watchdog command server socket"),
 				 errdetail("bind on \"%s\" failed with reason: \"%s\"", addr.sun_path, strerror(saved_errno))));
 	}
-	
+
 	if ( listen(sock, 5) < 0 )
 	{
 		/* listen failed */
@@ -1625,6 +1641,7 @@ static bool read_ipc_socket_and_process(int sock, bool *remove_socket)
 	ipcCommand = create_command_object(data_len);
 	ipcCommand->sourceIPCSocket = sock;
 	ipcCommand->commandSource = COMMAND_SOURCE_IPC;
+	ipcCommand->sourceWdNode = g_cluster.localNode;
 	ipcCommand->sourcePacket.type = type;
 	ipcCommand->sourcePacket.len = data_len;
 	gettimeofday(&ipcCommand->commandTime, NULL);
@@ -2120,9 +2137,10 @@ static IPC_CMD_PREOCESS_RES process_failover_command_on_coordinator(WDCommandDat
 	{
 		MemoryContext oldCxt;
 		ereport(DEBUG1,
-				(errmsg("proceeding with the failover command [%s] request from pgpool-II node \"%s\"",
+				(errmsg("proceeding with the failover command [%s] request from %s",
 						func_name,
-						ipcCommand->sourceWdNode->nodeName),
+						ipcCommand->commandSource == COMMAND_SOURCE_IPC?
+						"local pgpool-II":ipcCommand->sourceWdNode->nodeName),
 				 errdetail("no similar failover is in progress")));
 		/*
 		 * okay now ask all nodes to start failover
@@ -5062,9 +5080,8 @@ static int watchdog_state_machine_coordinator(WD_EVENTS event, WatchdogNode* wdN
 					 */
 					if (g_cluster.quorum_status == -1)
 					{
-						g_cluster.escalated = false;
 						ereport(LOG,
-								(errmsg("I am the cluster leader node but we do not have enough nodes in cluster"),
+							(errmsg("I am the cluster leader node but we do not have enough nodes in cluster"),
 								 errdetail("waiting for the quorum to start escalation process")));
 					}
 					else
@@ -5399,6 +5416,7 @@ static void start_escalated_node(void)
 	if (g_cluster.escalation_pid > 0)
 	{
 		g_cluster.escalated = true;
+		set_watchdog_node_escalated();
 		ereport(LOG,
 				(errmsg("escalation process started with PID:%d",g_cluster.escalation_pid)));
 		if (strlen(g_cluster.localNode->delegate_ip) > 0)
@@ -5406,7 +5424,6 @@ static void start_escalated_node(void)
 	}
 	else
 	{
-		g_cluster.escalated = false;
 		ereport(LOG,
 				(errmsg("failed to start escalation process")));
 	}
@@ -5438,6 +5455,7 @@ static void resign_from_escalated_node(void)
 	g_cluster.de_escalation_pid = fork_plunging_process();
 	g_cluster.holding_vip = false;
 	g_cluster.escalated = false;
+	reset_watchdog_node_escalated();
 }
 
 /*
diff --git a/src/watchdog/wd_commands.c b/src/watchdog/wd_commands.c
index dd6ae58..08d5fe9 100644
--- a/src/watchdog/wd_commands.c
+++ b/src/watchdog/wd_commands.c
@@ -66,6 +66,12 @@ static WDFailoverCMDResults wd_get_failover_result_from_data(WDIPCCmdResult *res
 
 /* shared memory variables */
 char *watchdog_ipc_address = NULL;
+bool *watchdog_require_cleanup = NULL;	/* shared memory variable set to true
+										 * when watchdog process terminates abnormally
+										 */
+bool *watchdog_node_escalated = NULL;	/* shared memory variable set to true
+										 * when watchdog process has performed escalation
+										 */
 unsigned int *ipc_shared_key = NULL;   /* key lives in shared memory
 										* used to identify the ipc internal
 										* clients
@@ -92,6 +98,18 @@ void wd_ipc_initialize_data(void)
 			pool_random_salt((char*)ipc_shared_key);
 		}
 	}
+
+	if (watchdog_require_cleanup == NULL)
+	{
+		watchdog_require_cleanup = pool_shared_memory_create(sizeof(bool));
+		*watchdog_require_cleanup = false;
+	}
+
+	if (watchdog_node_escalated == NULL)
+	{
+		watchdog_node_escalated = pool_shared_memory_create(sizeof(bool));
+		*watchdog_node_escalated = false;
+	}
 }
 
 char* get_watchdog_ipc_address(void)
@@ -104,6 +122,37 @@ unsigned int* get_ipc_shared_key(void)
 	return ipc_shared_key;
 }
 
+void set_watchdog_process_needs_cleanup(void)
+{
+	*watchdog_require_cleanup = true;
+}
+
+void reset_watchdog_process_needs_cleanup(void)
+{
+	*watchdog_require_cleanup = false;
+}
+
+bool get_watchdog_process_needs_cleanup(void)
+{
+	return *watchdog_require_cleanup;
+}
+
+
+void set_watchdog_node_escalated(void)
+{
+	*watchdog_node_escalated = true;
+}
+
+void reset_watchdog_node_escalated(void)
+{
+	*watchdog_node_escalated = false;
+}
+
+bool get_watchdog_node_escalation_state(void)
+{
+	return *watchdog_node_escalated;
+}
+
 /*
  * function issues the command to watchdog process over the watchdog
  * IPC command socket.
diff --git a/src/watchdog/wd_escalation.c b/src/watchdog/wd_escalation.c
index 24bb577..239bc84 100644
--- a/src/watchdog/wd_escalation.c
+++ b/src/watchdog/wd_escalation.c
@@ -137,7 +137,7 @@ fork_escalation_process(void)
 	{
 		if (wd_IP_up() != WD_OK)
 			ereport(WARNING,
-				(errmsg("watchdog de-escalation failed to bring down delegate IP")));
+				(errmsg("watchdog escalation failed to acquire delegate IP")));
 
 	}
 	exit(0);
diff --git a/src/watchdog/wd_if.c b/src/watchdog/wd_if.c
index 34e08cd..e92f4a3 100644
--- a/src/watchdog/wd_if.c
+++ b/src/watchdog/wd_if.c
@@ -103,22 +103,49 @@ wd_IP_up(void)
 {
 	int rtn = WD_OK;
 	char path[WD_MAX_PATH_LEN];
-	char cmd[128];
+	char* command;
 	int i;
 
 	if (strlen(pool_config->delegate_IP) == 0)
-		return WD_NG;
+	{
+		ereport(LOG,
+			(errmsg("trying to acquire the delegate IP address, but delegate IP is not configured")));
+		return WD_OK;
+	}
 
-	wd_get_cmd(cmd,pool_config->if_up_cmd);
-	snprintf(path,sizeof(path),"%s/%s",pool_config->if_cmd_path,cmd);
-	rtn = exec_if_cmd(path,pool_config->if_up_cmd);
+	command = wd_get_cmd(pool_config->if_up_cmd);
+	if (command)
+	{
+		snprintf(path,sizeof(path),"%s/%s",pool_config->if_cmd_path,command);
+		rtn = exec_if_cmd(path,pool_config->if_up_cmd);
+		pfree(command);
+	}
+	else
+	{
+		ereport(LOG,
+			(errmsg("failed to acquire the delegate IP address"),
+				 errdetail("unable to parse the if_up_cmd:\"%s\"",pool_config->if_up_cmd)));
+		return WD_NG;
+	}
 
 	if (rtn == WD_OK)
 	{
-		wd_get_cmd(cmd,pool_config->arping_cmd);
-		snprintf(path,sizeof(path),"%s/%s",pool_config->arping_path,cmd);
-		rtn = exec_if_cmd(path,pool_config->arping_cmd);
+		command = wd_get_cmd(pool_config->arping_cmd);
+		if (command)
+		{
+			snprintf(path,sizeof(path),"%s/%s",pool_config->arping_path,command);
+			rtn = exec_if_cmd(path,pool_config->arping_cmd);
+			pfree(command);
+		}
+		else
+		{
+			rtn = WD_NG;
+			ereport(LOG,
+				(errmsg("failed to acquire the delegate IP address"),
+					 errdetail("unable to parse the arping_cmd:\"%s\"",pool_config->arping_cmd)));
+		}
 	}
+
 	if (rtn == WD_OK)
 	{
 		for (i = 0; i < WD_TRY_PING_AT_IPUP; i++)
@@ -126,7 +153,7 @@ wd_IP_up(void)
 			if (wd_is_ip_exists(pool_config->delegate_IP) == true)
 				break;
 			ereport(LOG,
-				(errmsg("watchdog bringing up delegate IP"),
+				(errmsg("waiting for the delegate IP address to become active"),
 					 errdetail("waiting... count: %d", i+1)));
 		}
 
@@ -136,72 +163,74 @@ wd_IP_up(void)
 
 	if (rtn == WD_OK)
 		ereport(LOG,
-			(errmsg("watchdog bringing up delegate IP, 'if_up_cmd' succeeded")));
+			(errmsg("successfully acquired the delegate IP:\"%s\"",pool_config->delegate_IP),
+				 errdetail("'if_up_cmd' returned with success")));
 	else
-		ereport(WARNING,
-			(errmsg("watchdog failed to bring up delegate IP, 'if_up_cmd' failed")));
+		ereport(LOG,
+			(errmsg("failed to acquire the delegate IP address"),
+				 errdetail("'if_up_cmd' failed")));
 	return rtn;
 }
 
-#define WD_TRY_PING_AT_IPDOWN 3
 int
 wd_IP_down(void)
 {
 	int rtn = WD_OK;
 	char path[WD_MAX_PATH_LEN];
-	char cmd[128];
-	int i;
+	char* command;
 
 	if (strlen(pool_config->delegate_IP) == 0)
-		return WD_NG;
-
-	wd_get_cmd(cmd,pool_config->if_down_cmd);
-	snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, cmd);
-	rtn = exec_if_cmd(path,pool_config->if_down_cmd);
-
-	if (rtn == WD_OK)
 	{
-		for (i = 0; i < WD_TRY_PING_AT_IPDOWN; i++)
-		{
-			if (wd_is_ip_exists(pool_config->delegate_IP) == false)
-				break;
-		}
+		ereport(LOG,
+			(errmsg("trying to release the delegate IP address, but delegate IP is not configured")));
+		return WD_OK;
+	}
 
-		if (i >= WD_TRY_PING_AT_IPDOWN)
-			rtn = WD_NG;
+	command = wd_get_cmd(pool_config->if_down_cmd);
+	if (command)
+	{
+		snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, command);
+		rtn = exec_if_cmd(path,pool_config->if_down_cmd);
+		pfree(command);
+	}
+	else
+	{
+		ereport(LOG,
+			(errmsg("failed to release the delegate IP address"),
+				 errdetail("unable to parse the if_down_cmd:\"%s\"",pool_config->if_down_cmd)));
+		return WD_NG;
 	}
 
 	if (rtn == WD_OK)
 	{
 		ereport(LOG,
-			(errmsg("watchdog bringing down delegate IP"),
-				 errdetail("if_down_cmd succeeded")));
+			(errmsg("successfully released the delegate IP:\"%s\"",pool_config->delegate_IP),
+				 errdetail("'if_down_cmd' returned with success")));
 	}
 	else
 	{
-		ereport(WARNING,
-			(errmsg("watchdog bringing down delegate IP, if_down_cmd failed")));
+		ereport(LOG,
+			(errmsg("failed to release the delegate IP:\"%s\"",pool_config->delegate_IP),
+				 errdetail("'if_down_cmd' failed")));
 	}
 	return rtn;
 }
 
 
-int
-wd_get_cmd(char * buf, char * cmd)
+char*
+wd_get_cmd(char* cmd)
 {
-	int i,j;
-	i = 0;
-	while(isspace(cmd[i]) != 0)
-	{
-		i++;
-	}
-	j = 0;
-	while(isspace(cmd[i]) == 0)
+	char *command = NULL;
+
+	if (cmd && *cmd)
 	{
-		buf[j++] = cmd[i++];
+		char* tmp_str = pstrdup(cmd);
+		char* token = strtok(tmp_str," ");
+		if (token)
+			command = pstrdup(token);
+		pfree(tmp_str);
 	}
-	buf[j] = '\0';
-	return strlen(buf);
+	return command;
 }
 
 static int
diff --git a/src/watchdog/wd_utils.c b/src/watchdog/wd_utils.c
index 24cefb3..e3c5db2 100644
--- a/src/watchdog/wd_utils.c
+++ b/src/watchdog/wd_utils.c
@@ -55,7 +55,7 @@ typedef struct {
 void wd_check_network_command_configurations(void)
 {
 	char path[128];
-	char cmd[128];
+	char* command;
 
 	if (pool_config->use_watchdog == 0)
 		return;
@@ -67,34 +67,65 @@ void wd_check_network_command_configurations(void)
 		return;
 
 	/* check setuid bit of ifup command */
-	wd_get_cmd(cmd, pool_config->if_up_cmd);
-	snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, cmd);
-	if (! has_setuid_bit(path))
+	command = wd_get_cmd(pool_config->if_up_cmd);
+	if (command)
 	{
-		ereport(WARNING,
-			(errmsg("checking setuid bit of if_up_cmd"),
-				 errdetail("ifup[%s] doesn't have setuid bit", path)));
+		snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, command);
+		pfree(command);
+		if (! has_setuid_bit(path))
+		{
+			ereport(WARNING,
+				(errmsg("checking setuid bit of if_up_cmd"),
+					 errdetail("ifup[%s] doesn't have setuid bit", path)));
+		}
+	}
+	else
+	{
+		ereport(FATAL,
+			(errmsg("invalid configuration for if_up_cmd parameter"),
+					errdetail("unable to get command from \"%s\"",pool_config->if_up_cmd)));
 	}
 	/* check setuid bit of ifdown command */
-	wd_get_cmd(cmd, pool_config->if_down_cmd);
-	snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, cmd);
-	if (! has_setuid_bit(path))
+
+	command = wd_get_cmd(pool_config->if_down_cmd);
+	if (command)
 	{
-		ereport(WARNING,
-			(errmsg("checking setuid bit of if_down_cmd"),
-				 errdetail("ifdown[%s] doesn't have setuid bit", path)));
+		snprintf(path, sizeof(path), "%s/%s", pool_config->if_cmd_path, command);
+		pfree(command);
+		if (! has_setuid_bit(path))
+		{
+			ereport(WARNING,
+				(errmsg("checking setuid bit of if_down_cmd"),
+					 errdetail("ifdown[%s] doesn't have setuid bit", path)));
+		}
 	}
-	
+	else
+	{
+		ereport(FATAL,
+			(errmsg("invalid configuration for if_down_cmd parameter"),
+					errdetail("unable to get command from \"%s\"",pool_config->if_down_cmd)));
+	}
+
 	/* check setuid bit of arping command */
-	wd_get_cmd(cmd, pool_config->arping_cmd);
-	snprintf(path, sizeof(path), "%s/%s", pool_config->arping_path, cmd);
-	if (! has_setuid_bit(path))
+	command = wd_get_cmd(pool_config->arping_cmd);
+	if (command)
 	{
-		ereport(WARNING,
-			(errmsg("checking setuid bit of arping command"),
-				 errdetail("arping[%s] doesn't have setuid bit", path)));
-		
+		snprintf(path, sizeof(path), "%s/%s", pool_config->arping_path, command);
+		pfree(command);
+		if (! has_setuid_bit(path))
+		{
+			ereport(WARNING,
+				(errmsg("checking setuid bit of arping command"),
+					 errdetail("arping[%s] doesn't have setuid bit", path)));
+		}
 	}
+	else
+	{
+		ereport(FATAL,
+			(errmsg("invalid configuration for arping_cmd parameter"),
+					errdetail("unable to get command from \"%s\"",pool_config->arping_cmd)));
+	}
+
 }
 
 /*
V3_6_1-V3_6_STABLE.diff (51,399 bytes)

jakubs

2017-02-28 17:49

reporter   ~0001369

It seems that this patch works. I have another problem but I will make separate bug when I will know what is going on.

t-ishii

2017-03-26 16:21

developer   ~0001398

Close this issue.

Issue History

Date Modified Username Field Change
2017-01-30 22:55 jakubs New Issue
2017-01-30 22:55 jakubs File Added: pgpoolLog.txt
2017-01-30 22:56 jakubs File Added: hangPgPool2Postgres.pcap
2017-01-30 22:56 jakubs File Added: hangTomcat2PgPool.pcap
2017-02-03 14:56 t-ishii Note Added: 0001322
2017-02-03 17:28 jakubs Note Added: 0001323
2017-02-03 17:33 t-ishii Note Added: 0001324
2017-02-03 17:43 jakubs Note Added: 0001325
2017-02-03 17:50 t-ishii Note Added: 0001326
2017-02-06 08:37 t-ishii Assigned To => t-ishii
2017-02-06 08:37 t-ishii Status new => assigned
2017-02-06 08:37 t-ishii Status assigned => feedback
2017-02-16 21:48 jakubs Note Added: 0001348
2017-02-16 21:48 jakubs Status feedback => assigned
2017-02-23 17:03 t-ishii Note Added: 0001359
2017-02-23 17:03 t-ishii Status assigned => feedback
2017-02-23 21:38 jakubs Note Added: 0001362
2017-02-23 21:38 jakubs Status feedback => assigned
2017-02-24 07:49 t-ishii Note Added: 0001364
2017-02-24 07:49 t-ishii File Added: V3_6_1-V3_6_STABLE.diff
2017-02-24 07:50 t-ishii Status assigned => feedback
2017-02-28 17:49 jakubs Note Added: 0001369
2017-02-28 17:49 jakubs Status feedback => assigned
2017-03-26 16:21 t-ishii Note Added: 0001398
2017-03-26 16:21 t-ishii Status assigned => resolved