[pgsql-jp: 38122] Re: 強制的に接続をクローズ

Yasuo Ohgaki yohgaki @ ohgaki.net
2007年 3月 8日 (木) 12:21:40 JST


大垣です。

ハングするSQLがCOPY FORM STDINだったので入力待ちと思い込んでいた
のですが、試しに簡単なプログラムを作ると原因は別の部分と解りました。

#include <pgsql/libpq-fe.h>

int main(int argc, char *argv[]) {
        PGconn *conn;
        PGresult *res;

        conn = PQconnectdb("host=localhost");

        res = PQexec(conn, "CREATE TABLE test (test integer);");
        PQclear(res);
printf("MSG: %s\n", PQerrorMessage(conn));
        res = PQexec(conn, "COPY test FROM STDIN WITH DELIMITER ',' CSV QUOTE '\"' ESCAPE '\"'");
        PQclear(res);
printf("MSG: %s\n", PQerrorMessage(conn));
        //PQresetStart(conn);

        PQfinish(conn);

        return (0);
}

を実行する直ぐに終了してくれました。

問題のプログラムをgdbでアタッチ、バックトレースすると以下でした。

(gdb) bt
#0  0x0052897a in ?? () from /usr/lib/libpq.so.4
#1  0x0052f0f1 in PQgetResult () from /usr/lib/libpq.so.4
#2  0x003fa160 in zif_pg_dbname () from /usr/lib/php5/pgsql.so
#3  0x082413d2 in list_entry_destructor ()
#4  0x0823e897 in zend_hash_apply_deleter ()
#5  0x0823eb28 in zend_hash_graceful_reverse_destroy ()
#6  0x08235b39 in zend_deactivate ()
#7  0x081f7fa0 in php_request_shutdown ()
#8  0x082ade23 in main ()

TANIDA Yutaka wrote:
> 谷田です。
> 
> On Thu, 08 Mar 2007 09:18:56 +0900
> Yasuo Ohgaki <yohgaki @ ohgaki.net> wrote:
> 
>> libpqでDB接続をクローズする場合、PQfinishを利用しますが
>>
>> COPY test FROM STDIN WITH DELIMITER ',' CSV QUOTE '\"' ESCAPE '\"'";
>>
>> のようなコマンドを実行してからPQfinishを呼んでも(実行完了
>> を待ち続けるため)接続を終了できません。
>>
>> インタラクティブなアプリケーションであればCTRL-Cで終了でも
>> 構わないかも知れませんが、非インタラクティブなアプリケーション
>> ではCTRL-Cは解決策になりません。
> 
> 単にPQcancel関数でキャンセルというのは駄目ですか?
> 

私が利用しているPostgreSQLはこれで大丈夫なようです。
ありがとうございます。

私以外の環境のバックトレースでは

#0  0xa7ba88c0 in free () from /lib/tls/libc.so.6
#1  0xa7ec8ea7 in PQclear () from /usr/lib/libpq.so.5
#2  0x08086fc8 in _close_pgsql_link (rsrc=0x81e43ec) at
/usr/src/php-4.4.2/ext/pgsql/pgsql.c:277
#3  0x08139fb2 in list_entry_destructor (ptr=0x81e43ec) at
/usr/src/php-4.4.2/Zend/zend_list.c:177
#4  0x08137977 in zend_hash_apply_deleter (ht=0x81a49e0, p=0x81e43b4)
    at /usr/src/php-4.4.2/Zend/zend_hash.c:611
#5  0x08137b97 in zend_hash_graceful_reverse_destroy (ht=0x81a49e0)
    at /usr/src/php-4.4.2/Zend/zend_hash.c:677
#6  0x0812b9ed in shutdown_executor () at
/usr/src/php-4.4.2/Zend/zend_execute_API.c:211
#7  0x08133801 in zend_deactivate () at
/usr/src/php-4.4.2/Zend/zend.c:689
#8  0x08107862 in php_request_shutdown (dummy=0x0) at
/usr/src/php-4.4.2/main/main.c:999
#9  0x0814ee56 in main (argc=2, argv=0xafb6d114) at
/usr/src/php-4.4.2/sapi/cli/php_cli.c:881

となる物もあります。PostgreSQL/PHPのバージョンによっても多少動作
が異なるのかPQclearで待っているような感じ(ループかな?)なので別途
調査してみます。

最初のバックトレースでPQgetResultを呼んでいるのが分かりますが
これはすでに送信済みの非同期クエリが完了するのを待ってから終了
するために呼び出しています。(バックトレースを見るまで忘れてま
した)PQcancelだと互換性の問題があるので悩みます... 

-- 
Yasuo Ohgaki : yohgaki @ ohgaki.net : http://www.ohgaki.net/





pgsql-jp メーリングリストの案内