Skip to content

Override console Ctrl+C event handler with handler in module signal #1951

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

Merged
merged 2 commits into from
Apr 26, 2025

Conversation

BCSharp
Copy link
Member

@BCSharp BCSharp commented Apr 25, 2025

This is basically a fix for the signal module on POSIX. What was happening was that on POSIX, signals (to be more accurate: SIGINT only) are handled by SimpleSignalState, which installs a ConsoleCancelEventHandler on Console.CancelKeyPress. However, BasicConsole also installs its handler to handle Ctrl+C, and it happens very early during execution, way before module signal can be imported. Since the event handlers are executed in the order of registrations, BasicConsole is seeing the event before signal, calling ThreadAbort (which obviously does not work on .NET), and module signal had no chance to even react to SIGINT. This means that setting SIGINT to be ignored, or to terminate the program, or to call a custom event handler was ineffective.

This problem does not occur on Windows because NtSignalState installs its event handler by making a syscall to SetConsoleCtrlHandler in kernel32.dll, which does its callbacks in a "last registered — first called" fashion, so the late registration in signal overrules BasicConsole.

There is no straightforward way to prevent BasicConsole to register its event handler, but there is a way to override what it does by modifying a public property on BasicConsole, and this is what this PR does. The only quirk here was that the reference to a BasicConsole instance was not readily available to modules, so I added a new property on PythonContext to provide it. If there is a better way of doing it I would be glad to hear it.

/// <summary>
/// Not null if the Python context is running in a console host.
/// </summary>
internal IConsole/*?*/ Console { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

Could do a #nullable enable / #nullable restore?

@BCSharp BCSharp merged commit 604d5f1 into IronLanguages:main Apr 26, 2025
15 of 17 checks passed
@BCSharp BCSharp deleted the signal_console branch April 26, 2025 04:42
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