• Tom Lane's avatar
    Improve libpq's error recovery for connection loss during COPY. · fa4440f5
    Tom Lane authored
    In pqSendSome, if the connection is already closed at entry, discard any
    queued output data before returning.  There is no possibility of ever
    sending the data, and anyway this corresponds to what we'd do if we'd
    detected a hard error while trying to send().  This avoids possible
    indefinite bloat of the output buffer if the application keeps trying
    to send data (or even just keeps trying to do PQputCopyEnd, as psql
    indeed will).
    
    Because PQputCopyEnd won't transition out of PGASYNC_COPY_IN state
    until it's successfully queued the COPY END message, and pqPutMsgEnd
    doesn't distinguish a queuing failure from a pqSendSome failure,
    this omission allowed an infinite loop in psql if the connection closure
    occurred when we had at least 8K queued to send.  It might be worth
    refactoring so that we can make that distinction, but for the moment
    the other changes made here seem to offer adequate defenses.
    
    To guard against other variants of this scenario, do not allow
    PQgetResult to return a PGRES_COPY_XXX result if the connection is
    already known dead.  Make sure it returns PGRES_FATAL_ERROR instead.
    
    Per report from Stephen Frost.  Back-patch to all active branches.
    fa4440f5
fe-exec.c 88.1 KB