Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions src/core/IronPython.Modules/NtSignalState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

#nullable enable

using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
Expand All @@ -13,17 +15,19 @@
namespace IronPython.Modules {
public static partial class PythonSignal {
[SupportedOSPlatform("windows")]
internal class NtSignalState : PythonSignalState {
//We use a single Windows event handler to process all signals. This handler simply
//delegates the work out to PySignalToPyHandler.
public NativeSignal.WinSignalsHandler WinAllSignalsHandlerDelegate;
private class NtSignalState : PythonSignalState {
// We use a single Windows event handler to process all signals. This handler simply
// delegates the work out to PySignalToPyHandler.
public NativeWindowsSignal.WinSignalsHandler WinAllSignalsHandlerDelegate;


public NtSignalState(PythonContext pc) : base(pc) {
WinAllSignalsHandlerDelegate = new NativeSignal.WinSignalsHandler(WindowsEventHandler);
NativeSignal.SetConsoleCtrlHandler(this.WinAllSignalsHandlerDelegate, true);
WinAllSignalsHandlerDelegate = new NativeWindowsSignal.WinSignalsHandler(WindowsEventHandler);
NativeWindowsSignal.SetConsoleCtrlHandler(this.WinAllSignalsHandlerDelegate, true);
}

//Our implementation of WinSignalsHandler

// Our implementation of WinSignalsHandler
private bool WindowsEventHandler(uint winSignal) {
bool retVal;
int pySignal;
Expand Down Expand Up @@ -53,27 +57,27 @@ private bool WindowsEventHandler(uint winSignal) {
int tempId = (int)PySignalToPyHandler[pySignal];

if (tempId == SIG_DFL) {
//SIG_DFL - we let Windows do whatever it normally would
// SIG_DFL - we let Windows do whatever it normally would
retVal = false;
} else if (tempId == SIG_IGN) {
//SIG_IGN - we do nothing, but tell Windows we handled the signal
// SIG_IGN - we do nothing, but tell Windows we handled the signal
retVal = true;
} else {
throw new Exception("unreachable");
}
} else if (PySignalToPyHandler[pySignal] == default_int_handler) {
if (pySignal != SIGINT) {
//We're dealing with the default_int_handlerImpl which we
//know doesn't care about the frame parameter
// We're dealing with the default_int_handlerImpl which we
// know doesn't care about the frame parameter
retVal = true;
default_int_handlerImpl(pySignal, null);
} else {
//Let the real interrupt handler throw a KeyboardInterrupt for SIGINT.
//It handles this far more gracefully than we can
// Let the real interrupt handler throw a KeyboardInterrupt for SIGINT.
// It handles this far more gracefully than we can
retVal = false;
}
} else {
//We're dealing with a callable matching PySignalHandler's signature
// We're dealing with a callable matching PySignalHandler's signature
retVal = true;
PySignalHandler temp = (PySignalHandler)Converter.ConvertToDelegate(PySignalToPyHandler[pySignal],
typeof(PySignalHandler));
Expand All @@ -96,7 +100,9 @@ private bool WindowsEventHandler(uint winSignal) {
}
}

internal static class NativeSignal {

[SupportedOSPlatform("windows")]
internal static class NativeWindowsSignal {
// Windows API expects to be given a function pointer like this to handle signals
internal delegate bool WinSignalsHandler(uint winSignal);

Expand Down
37 changes: 15 additions & 22 deletions src/core/IronPython.Modules/SimpleSignalState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,49 @@

namespace IronPython.Modules {
public static partial class PythonSignal {
internal class SimpleSignalState : PythonSignalState {
private class SimpleSignalState : PythonSignalState {

public SimpleSignalState(PythonContext pc)
: base(pc) {
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
}

private void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e) {
int pySignal;
switch (e.SpecialKey) {
case ConsoleSpecialKey.ControlC:
pySignal = SIGINT;
break;

case ConsoleSpecialKey.ControlBreak:
pySignal = SIGBREAK;
break;

default:
throw new InvalidOperationException("unreachable");
}
private void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e) {
int pySignal = e.SpecialKey switch {
ConsoleSpecialKey.ControlC => SIGINT,
ConsoleSpecialKey.ControlBreak => SIGBREAK,
_ => throw new InvalidOperationException("unreachable"),
};

lock (PySignalToPyHandler) {
if (PySignalToPyHandler[pySignal].GetType() == typeof(int)) {
int tempId = (int)PySignalToPyHandler[pySignal];

if (tempId == SIG_DFL) {
//SIG_DFL - do whatever it normally would
// SIG_DFL - do whatever it normally would
return;
} else if (tempId == SIG_IGN) {
//SIG_IGN - we do nothing, but tell the OS we handled the signal
// SIG_IGN - we do nothing, but tell the OS we handled the signal
e.Cancel = false;
return;
} else {
throw new Exception("unreachable");
}
} else if (PySignalToPyHandler[pySignal] == default_int_handler) {
if (pySignal != SIGINT) {
//We're dealing with the default_int_handlerImpl which we
//know doesn't care about the frame parameter
// We're dealing with the default_int_handlerImpl which we
// know doesn't care about the frame parameter
e.Cancel = true;
default_int_handlerImpl(pySignal, null);
return;
} else {
//Let the real interrupt handler throw a KeyboardInterrupt for SIGINT.
//It handles this far more gracefully than we can
// Let the real interrupt handler throw a KeyboardInterrupt for SIGINT.
// It handles this far more gracefully than we can
return;
}
} else {
//We're dealing with a callable matching PySignalHandler's signature
// We're dealing with a callable matching PySignalHandler's signature
PySignalHandler temp = (PySignalHandler)Converter.ConvertToDelegate(PySignalToPyHandler[pySignal],
typeof(PySignalHandler));

Expand All @@ -86,4 +80,3 @@ private void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e) {
}

#endif

6 changes: 4 additions & 2 deletions src/core/IronPython.Modules/nt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1870,13 +1870,15 @@ public static void kill(CodeContext/*!*/ context, int pid, int sig) {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
killUnix(pid, sig);
} else {
if (PythonSignal.NativeSignal.GenerateConsoleCtrlEvent((uint)sig, (uint)pid)) return;
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
if (PythonSignal.NativeWindowsSignal.GenerateConsoleCtrlEvent((uint)sig, (uint)pid)) return;

// If the calls to GenerateConsoleCtrlEvent didn't work, simply
// forcefully kill the process.
Process toKill = Process.GetProcessById(pid);
toKill.Kill();
} else {
throw new PlatformNotSupportedException();
}
}

Expand Down
Loading