eXile has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm trying to make an existing DBI::Proxy-using GUI-app. more robust by trying to make it recover from a network failure. Right now I'm puzzled by a 'broken pipe' message I get on the client-side when I break the network connection between client and server. After this message the app. stops, I can't seem to catch this with an 'eval'. The code is something like:

my $retval = eval { $sth->execute(@values); }; unless ($retval) { _db_recover(); } ... sub _db_recover { eval { $dbh->disconnect(); }; warn("reconnecting to database in 20 seconds\n"); sleep 20; eval { $dbh->connect(@somevalues); }; }
Note this is still in development, I don't want to reconnect everytime the execute fails.

I've also tried to change the signal-hash locally to 'IGNORE' the $SIG{PIPE} and $SIG{DIE} signals (in fact I've even tried to set the values of the whole %SIG to 'IGNORE') but the app. still stops executing.

While debugging I found DBD::Proxy holds an IO::Socket that gets disconnected when I disconnect the network connection (duh), this most probably causes the 'broken pipe' message, but I can't bend my mind around how to access this Socket or how to recreate it after a network failure.

Any idea's on how I can keep my app. (at least) running in these situations?

Update: fixed $dbh->execute to $sth->execute

Replies are listed 'Best First'.
Re: script dies with 'broken pipe'-message, even in eval
by mifflin (Curate) on May 25, 2004 at 16:46 UTC
    try replacing ..
    my $retval = eval { $dbh->execute(@values); }; unless ($retval) { _db_recover(); }
    with...
    eval { $dbh->execute(@values); }; if ($@) { _db_recover(); }
      The code:
      eval { $dbh->execute(@values); }; if ($@) { _db_recover(); }
      was actually my first try. But there was nothing in $@ , so _db_recover() was never executed. The returnvalue-for-eval did the trick and at least got the _db_recover() function executed.
        Ah! I see an issue.
        you are using a database handle ($dbh) to execute something. execute is a method for a statement handle ($sth). Also...
        How are you setting up your database connection?
        Are you setting RaiseError?
        $dbh = DBI->connect( 'dbi:Oracle:tnsname', 'userid', 'password', {RaiseError => 1} );
        If not you would have to check for an error after every call like ...
        $sth->execute(@args) || die $sth->errstr();
        Instead of being able to trap errors in an eval