mojolicious / mojo-pg

Mojolicious :heart: PostgreSQL
https://metacpan.org/release/Mojo-Pg
Artistic License 2.0
101 stars 46 forks source link

Infinity loop while non-blocking query #3

Closed Logioniz closed 9 years ago

Logioniz commented 9 years ago

code:

#!/usr/bin/perl

use strict;
use warnings;
use v5.10;

use Mojo::Pg;
use Mojo::IOLoop;

my $pg = Mojo::Pg->new('postgresql://logioniz@/test')->max_connections(1)->max_statements(1);
my $db = $pg->db;

$db->query(q{create table if not exists qwe (num integer, text text)});
$db->query(q{truncate qwe});

Mojo::IOLoop->delay(
  sub { $db->query(q{update qwe set num = ? where text = ?}, 1, '1' => shift->begin) },
  sub { $db->query(q{insert into qwe(num, text) values (?, ?)}, 1, '1' => shift->begin) },
  sub { Mojo::IOLoop->stop }
);

Mojo::IOLoop->start;
kraih commented 9 years ago

I can confirm the problem, but i think DBD::Pg might be at fault here, because the underlying pg_socket just doesn't become readable again.

    -> FETCH for DBD::Pg::st (DBI::st=HASH(0x7fa4c501c758)~INNER 'pg_async')
Begin dbd_st_FETCH (key: pg_async)
End dbd_st_FETCH_attrib
    <- FETCH= ( 0 ) [1 items] at lib/Mojo/Pg/Database.pm line 124 via  at lib/Mojo/Pg/Database.pm line 93
    -> prepare for DBD::Pg::db (DBI::db=HASH(0x7fa4c501c338)~0x7fa4c501c278 'insert into qwe(num, text) values (?, ?)' HASH(0x7fa4c4da8010))
Begin dbd_st_prepare (statement: insert into qwe(num, text) values (?, ?))
Begin pg_st_split_statement
End pg_st_split_statement
Immediate prepare decision: dml=1 direct=0 server_prepare=1 prepare_now=0 PGLIBVERSION=90401
End dbd_st_prepare
    <- prepare= ( DBI::st=HASH(0x7fa4c501c998) ) [1 items] at lib/Mojo/Pg/Database.pm line 128 via  at lib/Mojo/Pg/Database.pm line 93
    -> execute for DBD::Pg::st (DBI::st=HASH(0x7fa4c501c998)~0x7fa4c4d356f0 1 '1')
Begin dbd_bind_ph (ph_name: 1)
End dbd_bind_ph
Begin dbd_bind_ph (ph_name: 2)
End dbd_bind_ph
Begin dbd_st_execute
PQexec* decision: dml=1 direct=0 server_prepare=1 numbound=0 numphs=2 default=0 current=0
Early return for async queryEnd dbd_st_execute (async)
    <- execute= ( '0E0' ) [1 items] at lib/Mojo/Pg/Database.pm line 141 via  at lib/Mojo/Pg/Database.pm line 104
    -> pg_ready for DBD::Pg::db (DBI::db=HASH(0x7fa4c501c338)~0x7fa4c501c278)
Begin pg_db_ready (async status: 1)
End pg_db_ready
    <- pg_ready= ( 0 ) [1 items] at foo.pl line 26 via  at /Users/sri/perl5/perlbrew/perls/perl-5.20.2/lib/site_perl/5.20.2/Mojo/IOLoop/Delay.pm line 48
    <> DESTROY(DBI::st=HASH(0x7fa4c501c740)) ignored for outer handle (inner DBI::st=HASH(0x7fa4c501c758) has ref cnt 1)
    -> DESTROY for DBD::Pg::st (DBI::st=HASH(0x7fa4c501c758)~INNER)
Begin dbd_st_destroy
Begin handle_old_sync (flag: 4)
Waiting for old async command to finish
Begin _sqlstate
End _sqlstate (imp_dbh->sqlstate: 00000)
End _sqlstate (status: 1)
End handle_old_async
End dbd_st_destroy
    <- DESTROY= ( undef ) [1 items] at lib/Mojo/Pg/Database.pm line 134 via  at lib/Mojo/Pg/Database.pm line 134
    dbih_clearcom 0x7fa4c501c758 (com 0x7fa4c3e17d60, type 3) done.

The trace for the insert statement also ends very suspiciously with a "Waiting for old async command to finish".

kraih commented 9 years ago

We might have to make a breaking change and remove the queue for non-blocking queries from Mojo::Pg::Database for now.

Logioniz commented 9 years ago

New version have warning's in console.

$ perl -MMojo::Pg -le 'print $Mojo::Pg::VERSION;'
2.0
$ cat 4.pl 
use strict;
use warnings;
use v5.10;

use Mojo::Pg;
use Mojo::IOLoop;

my $pg = Mojo::Pg->new('postgresql://alex@/test')->max_connections(1);
my $db = $pg->db;

$db->query(q{create table if not exists qwe (num integer, text text)});
$db->query(q{truncate qwe});

Mojo::IOLoop->delay(
  sub {
    my $d = shift;
    for (1 .. 5) {
      $pg->db->query(q{update qwe set num = ? where text = ?}, 1, '1' => $d->begin);
    }
  },
  sub {
    my $d = shift;
    for (1 .. 5) {
      $pg->db->query(q{insert into qwe(num, text) values (?, ?)}, 1, '1' => $d->begin);
    }
  },
  sub { }
)->wait;
$ perl 4.pl 
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
Mojo::Reactor::EV: I/O watcher failed: DBD::Pg::db pg_ready failed: could not receive data from server: Bad file descriptor at /usr/local/share/perl/5.18.2/Mojo/Pg/Database.pm line 132, <DATA> line 2231.
    (in cleanup) Can't call method "_step" on an undefined value at /usr/local/share/perl/5.18.2/Mojo/IOLoop/Delay.pm line 14, <DATA> line 2231 during global destruction.
Logioniz commented 9 years ago

Also have message below when use Mojo::Pg version 2.0 in Minion worker, but i can't invent simple solution which always have this warining.

DBD::Pg::st DESTROY failed: could not receive data from server: Bad file descriptor during global destruction.

kraih commented 9 years ago

Should be fixed now. https://github.com/kraih/mojo-pg/commit/68c9485e891a0e64a32fe605fd58ac049d18f68c

Logioniz commented 9 years ago

Thanks.

kraih commented 9 years ago

Another bug related to this has just been fixed. https://github.com/kraih/mojo-pg/commit/cf742aed51dff2233708832735c3b2209d2edc79