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
11 changes: 11 additions & 0 deletions src/core/IronPython.Modules/signal.NtSignalState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ public NtSignalState(PythonContext pc) : base(pc) {
}


protected override void Dispose(bool disposing) {
if (disposing) {
NativeWindowsSignal.SetConsoleCtrlHandler(this.WinAllSignalsHandlerDelegate, false);
} else {
var winAllSignalsHandlerDelegate = new NativeWindowsSignal.WinSignalsHandler(WindowsEventHandler);
NativeWindowsSignal.SetConsoleCtrlHandler(winAllSignalsHandlerDelegate, false);
}
base.Dispose(disposing);
}


// Our implementation of WinSignalsHandler
private bool WindowsEventHandler(uint winSignal) {
bool retVal;
Expand Down
14 changes: 13 additions & 1 deletion src/core/IronPython.Modules/signal.SimpleSignalState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System;
using System.Runtime.InteropServices;

using Microsoft.Scripting.Hosting.Shell;

using IronPython.Runtime;

namespace IronPython.Modules {
Expand All @@ -18,13 +20,23 @@ private class SimpleSignalState : PythonSignalState {

public SimpleSignalState(PythonContext pc) : base(pc) {
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
if (pc.Console is Microsoft.Scripting.Hosting.Shell.BasicConsole console) {
if (pc.Console is BasicConsole console) {
// in console hosting scenarios, we need to override the console handler of Ctrl+C
_consoleHandler = console.ConsoleCancelEventHandler;
console.ConsoleCancelEventHandler = null;
}
}

protected override void Dispose(bool disposing) {
if (disposing) {
Console.CancelKeyPress -= new ConsoleCancelEventHandler(Console_CancelKeyPress);
if (_consoleHandler != null && DefaultContext.DefaultPythonContext.Console is BasicConsole console) {
// restore the original console handler
console.ConsoleCancelEventHandler = _consoleHandler;
}
}
base.Dispose(disposing);
}

private void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e) {
int pySignal = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SIGINT
Expand Down
21 changes: 20 additions & 1 deletion src/core/IronPython.Modules/signal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ private static void SetPythonSignalState(CodeContext/*!*/ context, PythonSignalS
/// <summary>
/// This class is used to store the installed signal handlers.
/// </summary>
private class PythonSignalState {
private class PythonSignalState : IDisposable {
// this provides us with access to the Main thread's stack
public readonly PythonContext SignalPythonContext;

Expand Down Expand Up @@ -511,6 +511,25 @@ protected void CallPythonHandler(int signum, object? handler) {
}
}
}

public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}

~PythonSignalState() {
Dispose(false);
}

protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
Array.Clear(PySignalToPyHandler, 0, PySignalToPyHandler.Length);
}
_disposed = true;
}
}
private bool _disposed = false;
}


Expand Down
11 changes: 11 additions & 0 deletions src/core/IronPython/Runtime/PythonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -545,11 +545,16 @@ public object GetModuleState(object key) {
/// Sets per-runtime state used by a module. The module should have a unique key for
/// each piece of state it needs to store.
/// </summary>
/// <remarks>
/// The previous piece of state (if any) is disposed if it implements IDisposable.
/// </remarks>
public void SetModuleState(object key, object value) {
EnsureModuleState();

lock (_moduleState) {
_moduleState.TryGetValue(key, out object oldState);
_moduleState[key] = value;
(oldState as IDisposable)?.Dispose();
}
}

Expand Down Expand Up @@ -1319,6 +1324,12 @@ public override void Shutdown() {
Flush(SharedContext, SystemStandardOut);
Flush(SharedContext, SystemStandardError);

lock (_moduleState) {
foreach (var state in _moduleState.Values) {
(state as IDisposable)?.Dispose();
}
}

static void Flush(CodeContext context, object obj) {
if (obj is PythonIOModule._IOBase pf) {
if (!pf.closed)
Expand Down