Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hanging execution of queries like "COPY TO STDIN" in asynchronous mode. #98

Open
true-alex opened this issue Sep 5, 2022 · 2 comments
Assignees

Comments

@true-alex
Copy link

When calling "COPY ... TO STDIN" query in asynchronous mode after pg_ready returned 1, pg_result call hangs.

The reason is probably the implementation of the pg_db_result method in the dbdimp.c file. This method is written exactly with the libpq documentation, the async section, which says that PQgetResult must be called until it returns null. However, if PQgetResult returned a PGRES_COPY_* state, this state will not change until the copy operations are completed (according to the copy libpq documentation).

To test my theory, at the end of the main loop of the pg_db_result function, I put a check with a loop break:

diff -r DBD-Pg-3.15.1/dbdimp.c DBD-Pg-3.15.1_patch/dbdimp.c
5375a5376,5378
>         if ( rows == -1 ) {
>               break;
>         }

In the attachments there are two greatly simplified files, one synchronous one works correctly, the second asynchronous one without a patch freezes, with a patch it works correctly.

The problem has been reproduced on:
Freebsd 9.4 + Postgress 9.3
Cenos 6 + Postgress 9.4
OracleLinux 8 + Postgress 13
Freebsd 13 + Postgress 13

test.tgz

@true-alex
Copy link
Author

When researching the problem, I used the documentation:
https://postgrespro.com/docs/postgrespro/13/libpq-copy
The functions of this section should be executed only after obtaining a result status of PGRES_COPY_OUT or PGRES_COPY_IN from PQexec or PQgetResult.
...
After PQgetCopyData returns -1, call PQgetResult to obtain the final result status of the COPY command. One can wait for this result to be available in the usual way. Then return to normal operation.

https://postgrespro.com/docs/postgresql/13/libpq-async
PQgetResult must be called repeatedly until it returns a null pointer, indicating that the command is done. (If called when no command is active, PQgetResult will just return a null pointer at once.) Each non-null result from PQgetResult should be processed using the same PGresult accessor functions previously described. Don't forget to free each result object with PQclear when done with it. Note that PQgetResult will block only if a command is active and the necessary response data has not yet been read by PQconsumeInput .

@turnstep
Copy link
Contributor

As mentioned in the PR, I don't think we should allow pg_result after a COPY, as it makes no sense to wait for the server, when the only way to finish is for the client to officially end things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants