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

I am working on a Perl program that connects to an Informix database. The Perl program may fork and execute an external program that also talks to the database. The external programs are compiled esql C code. The Perl program and the external program communicate via a UNIX socket, and the Perl program blocks until the external program finishes its business.

For some external programs it works, and for others sqlcode -349 "Database not selected yet" happens on the first esql statement attempted in the external program. From what I've read, child processes inherit database connections from the parent, so this error should never happen. The Perl program always has a connection to the database established before calling the external program.

The program is DBIx::Perform version 0.693 (in the authors section in CPAN under my name, bkchapin, as the original author of DBIx::Perform has not sanctioned my changes). The environment is HP-UX 11.11, Informix version 9.50C1, Perl 5.8.8 compiled with gcc, and gcc version 3.4.6. Originally, esql used the native C compiler, but I modified a copy to use gcc. esql for gcc is what I'm using now.

Any insight? Here comes confusion. I've been reading that some databases keep some kind of connection info variously called a "session ID", "connection ID", or "database handle" (so, an integer?) and I should fetch this information somehow in both parent and child and see if it's present and the same. I can't see that being the $dbh in $dbh = DBI->connect(...). Perhaps it's something like $dbh->{ix_ConnectionName}, but that is a name, not some kind of integer value like I'd expect a handle to be. Maybe there's some database query that would return this info, but that doesn't seem right either because if the child doesn't have a handle with which to connect, it can't very well query the database for a handle. Then there's $sth, and perhaps the 's' in that name is for "session" and I have "session ID" and "connection ID" conflated above? If I get this info, then there's some flag for "onstat" or some other db utlitity I can use to check things. No, I'm not a database guru, but I do well enough most of the time.

Replies are listed 'Best First'.
Re: DB connection after fork, exec
by gamache (Friar) on Oct 18, 2007 at 18:59 UTC
    The use of DBI in forked processes is well-described in this node.
Re: DB connection after fork, exec
by Joost (Canon) on Oct 18, 2007 at 18:53 UTC
    It seems you want to use the same connection from both the parent process and the child process.

    If so, you should at least make sure you set $^F to whatever is the correct value for your program, otherwise the exec()d child will not receive the database handle (since close-on-exec will - probably - be set) update: this may have no effect if the database socket is actually open()ed by C library code instead of perl code.

    Also, the child program should be written to support the notion of an inherited database handle - many database-using programs aren't - they just open their own connection.

    The integer you're looking for my be the fileno() of the database connection socket, but don't ask me how to get at that portably (or even non-portably).

    Or maybe I'm completely misinterpreting your question. It happens.

    update 2: from the DBI docs, it appears that child processes may inherit the database handle across a fork(), but 1) it says nothing about exec() and 2) it notes that some databases don't support doing that.