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

Workaround asyncio signal handling on Unix #479

Merged
merged 4 commits into from
Jan 14, 2021

Conversation

hidmic
Copy link
Contributor

@hidmic hidmic commented Jan 13, 2021

Unix asyncio loops override existing signal wakeup file descriptors with no regards for existing ones -- set by user code or by another loop. For further reference, see here. This is a problem when the child watcher gets lazy initialized (e.g. on first async subprocess execution, see here and here).

CI up to launch:

  • Linux Build Status
  • CentOS Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

Unix asyncio loops override existing signal wakeup file descriptors
with no regards for existing ones -- set by user code or by another
loop

Signed-off-by: Michel Hidalgo <[email protected]>
@hidmic
Copy link
Contributor Author

hidmic commented Jan 13, 2021

I'll open another ticket upstream. asyncio signal handling is awful.

Copy link
Member

@ivanpauno ivanpauno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really comfortable with the fact that this PR overwrites signal.set_wakeup_fd, but the code looks reasonable and I don't know how to fix this in another way.

It's worth writing a big comment explaining why this is being done in the code.

LGTM with nits addressed.

Signed-off-by: Michel Hidalgo <[email protected]>
@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

@ivanpauno PTAL @ a15958a

@ivanpauno
Copy link
Member

I'll open another ticket upstream. asyncio signal handling is awful.

does this PR mean that signal handlers added with asyncio.loop.add_signal_handler are ignored if you later happen to asynchronously launch a process?

Really, that's pretty broken 😄 ....

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

does this PR mean that signal handlers added with asyncio.loop.add_signal_handler are ignored if you later happen to asynchronously launch a process?

signal.set_wakeup_fd is called every time you do add_signal_handler, so not ignored, no. Problem is that asyncio loops do not cooperate with the rest of the system (or with each other). They own signal.set_wakeup_fd. If a signal handler gets added at the wrong time, whatever was set is gone.

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

what does happen in a multi-threaded scenario?

signal.set_wakeup_fd can only be used in the main thread.

But now that I think about it, I should enforce it for the AsyncSafeSignalManager too.

@ivanpauno
Copy link
Member

signal.set_wakeup_fd is called every time you do add_signal_handler, so not ignored, no. Problem is that asyncio loops do not cooperate with the rest of the system (or with each other). They own signal.set_wakeup_fd. If a signal handler gets added at the wrong time, whatever was set is gone.

I mean, does something like:

loop.add_signal_handler(...)
# first process launch in next line, child watcher initialized there
process = asyncio.create_subprocess_exec(...)

work, or is that also broken?

If that's not broken, if they would support add_signal_handler on Windows everything would be more happy ...

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

work, or is that also broken?

If it's the same loop for both calls, it works. If it's different loops, last one wins :D

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

f90f8bc should take care of multi-threaded scenarios. It's (I think) exception-safe too.

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

CI up to launch:

  • Linux Build Status
  • CentOS Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@hidmic
Copy link
Contributor Author

hidmic commented Jan 14, 2021

Alright, all's green and reviewer's happy. Going in!

@hidmic hidmic merged commit 60d2ef2 into master Jan 14, 2021
@hidmic hidmic deleted the hidmic/workaround-asyncio-signal-handling branch January 14, 2021 20:20
hidmic added a commit that referenced this pull request Jun 16, 2021
Unix asyncio loops override existing signal wakeup file descriptors with no regards for existing ones -- set by user code or by another loop

Signed-off-by: Michel Hidalgo <[email protected]>
hidmic added a commit that referenced this pull request Jun 29, 2021
Unix asyncio loops override existing signal wakeup file descriptors with no regards for existing ones -- set by user code or by another loop

Signed-off-by: Michel Hidalgo <[email protected]>
hidmic pushed a commit that referenced this pull request Jul 7, 2021
* Handle signals within the asyncio loop. (#476)
* Workaround asyncio signal handling on Unix (#479)
* Remove is_winsock_handle() and instead test if wrapping the handle in a socket.socket() works (#494)
* Close the socket pair used for signal management (#497)
* Only try to wrap the fd in a socket on Windows (#498)
* Bring back deprecated launch.utilities.signal_management APIs

Signed-off-by: Michel Hidalgo <[email protected]>
Signed-off-by: Ivan Santiago Paunovic <[email protected]>
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

Successfully merging this pull request may close these issues.

2 participants