-
Notifications
You must be signed in to change notification settings - Fork 158
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
connection.cancel can hang #491
Comments
Same here, after the connection was lost to the database, my process was hung, so I connected with gdb and saw that connection.cancel() did not return. Running aiopg 0.16.0 on python 3.6.7 on Ubuntu 18.04
EDIT: see this: psycopg/psycopg2#561. The underlying problem is a hung tcp connection, which psycopg doesn't have a good way of detection without setting a timeout on the socket. However, the fact that psycopg2.connection.cancel() hangs doesn't mean that aiopg should let it block the event loop. I agree with @thehesiod's suggestion that maybe aiopg could call it from a thread? |
Please clarify: is it a hang in |
In psycopg. But aiopg calls it from code running in the event loop. |
If |
I was mistaken earlier, the hanging call was not in aiopg.connection.cancel(), rather in the internal cancel() function in connection._poll(), on line 232 in connection.py as you see in the stack trace above. But now that I take a deeper look at the implementation of aiopg, I see that I was also mistaken about how the async is implemented. I had assumed that psycopg2 provides only a synchronous interface, and aiopg ran it in a thread pool behind the scenes. But now that I see that psycopg2 itself is the one implementing the async, It looks like the problem is that psycopg2 doesn't have an asynchronous implementation of cancel(). |
I just found this: psycopg/psycopg2#113 (comment)
|
And additionally, you're right. It's not the case I ran into, but in any case maybe cancel() should be removed from the API |
Would you make a PR for raising |
You don't prefer to use the blocking close in a thread? Seems a shame not
to provide close() if there's a way to implement it, not to mention the
fact that this would be a breaking API change.
And if not, what about the internal cancel in the exception handler? Should
it close the connection instead? This might also subtly break people's code
who expect the connection to remain open.
…On Fri, May 31, 2019, 21:10 Andrew Svetlov ***@***.***> wrote:
Would you make a PR for raising psycopg2.ProgrammingError unconditionally
if Connection.cancel() is called?
@vir-mir <https://github.com/vir-mir> could you track the discussion and
review/accept the proposed change?
Honestly, I prefer to don't spend my personal time on this project. I have
a lot of other FOSS projects where my involvement is crucial. I hope you
understand my position.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#491?email_source=notifications&email_token=AAEYDDNSLVR4A2SBDHAVTEDPYFSY3A5CNFSM4FM6BETKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWV7JEI#issuecomment-497808529>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEYDDPAKYXZET63O7UCYCDPYFSY3ANCNFSM4FM6BETA>
.
|
You can try to make a PR but I don't see how to mix sync and async mode for the same connection. It makes an unreliable mess at least.
No. Explicit raising an exception for a broken code is not the API breakage but a fix. It deserves a new library version to emphasize the change. Say again, if the feature is not provided by |
Yeah, sorry, haha, I meant cancel.
I think it would be possible to implement it pretty reasonably. Just start
a thread, cancel from the thread, and await the thread.
The cancel method currently does blocking io, but I don't know if it would
be fair to call it broken. It could be that lots of code uses and depends
on it, and it doesn't bother them so much that it isn't async.
And if we deprecate cancel, you didn't answer the question what to do about
the internal cancel in the _poll method.
…On Sat, Jun 1, 2019, 23:50 Andrew Svetlov ***@***.***> wrote:
1.
Are you talking about cancel() or close()?
2.
Seems a shame not
to provide close() if there's a way to implement it
You can try to make a PR but I don't see how to mix sync and async mode
for the same connection. It makes an unreliable mess at least.
1.
this would be a breaking API change
No. Explicit raising an exception for a broken code is not the API
breakage but a fix. It deserves a new library version to emphasize the
change.
Say again, if the feature is not provided by psycopg2 we should not to
emulate it.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#491?email_source=notifications&email_token=AAEYDDP7NRKTESWCGJF3M7DPYLOIZA5CNFSM4FM6BETKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWXIJ6Y#issuecomment-497976571>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEYDDMUJZPQJBM2SWXBRVDPYLOIZANCNFSM4FM6BETA>
.
|
Related: #375 |
Now that I think about it a bit more, starting a thread might not be up to standard, because someone could be using async to solve the C10K problem, and might make large numbers of calls to cancel() concurrently. In that case, starting a large number of threads might not be scalable. |
This is not about C10K problem but worse.
That's why I wrote: if psycopg2 doesn't support async cancel that aiopg should drop this (already not working and buggy) feature. |
Dropping the connection.cancel() feature is fine, but what to do if there
is an exception during a query?
…On Sun, Jun 2, 2019, 21:17 Andrew Svetlov ***@***.***> wrote:
This is not about C10K problem but worse.
TCP socket has two mutually exclusive modes: blocking and non-blocking.
Very simple, like Schrodinger's Cat life status :)
psycopg2 in async-mode switches connection sockets to non-blocking, this
feature is used by aiopg.
If psycopg2.connection.cancel() blocks it means that the socket is
non-blocking for everything except .cancel(). This is not supposed to
work by design.
That's why I wrote: if psycopg2 doesn't support async cancel that aiopg
should drop this (already not working and buggy) feature.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#491?email_source=notifications&email_token=AAEYDDKIJIHB7EKCCU3LDD3PYQFDXA5CNFSM4FM6BETKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWX3DTQ#issuecomment-498053582>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEYDDJL2RG4IX5S764WWQ3PYQFDXANCNFSM4FM6BETA>
.
|
Aaah, the answer is very simple: close the socket and drop the connection. |
You mean close the socket brutally with |
Sorry for that. |
psycopg2 doesn't have any better way of doing it than aiopg, since libpq doesn't expose an asynchronous way to do |
No. |
It doesn't use the same socket. PQcancel opens a new TCP connection to the server |
And again, removing it from the API doesn't solve the problem. We still need to cancel the query if there was an exception during a query. |
probably should call cancel from a executor |
I'm in favor. Happy to modify my PR accordingly |
Will do. aiopg is not the only FOSS project what I'm working on. |
bump? |
bump again? |
Still creates an issue for some of us. I guess there isn't much to do? |
we noticed this callstack in our prod server which hung our main thread breaking the server:
suggest
loop.run_in_executor
'ing it as supposedly this method is thread safe. Ideally there would be a timeout that affects this as well. I'm not sure if the DSNconnect_timeout
appliesThe text was updated successfully, but these errors were encountered: