// csc signal.cs using System; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void SignalHandler(int sig); public class SignalTest { [DllImport("msvcrt.dll", PreserveSig = true)] static extern int raise(int sig); [DllImport("msvcrt.dll", PreserveSig = true)] static extern SignalHandler signal(int sig, SignalHandler handler); // Store in a static to prevent it from being garbage collected static SignalHandler _Handler = new SignalHandler(MyHandler); const int SIGINT = 2; // Ctrl-C const int SIGFPE = 8; const int SIGTERM = 15; // process termination const int signalToTest = SIGFPE; static string GetCurrentThreadInfo() { return String.Format("{0}({1})", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId); } static void MyHandler(int sig) { Console.WriteLine("Signal {0} raised on thread {1}", sig, GetCurrentThreadInfo()); Console.WriteLine(new StackTrace()); signal(sig, _Handler); // reinstall handler so that we can keep looping Console.Write("In handler. Press any key..."); Console.ReadKey(); } static void RunTest() { Console.WriteLine("Test thread : " + GetCurrentThreadInfo()); signal(signalToTest, _Handler); while(true) { Console.Write("Press any key (q to abort)..."); ConsoleKeyInfo keyPressed = Console.ReadKey(); if (keyPressed.KeyChar == 'q') { break; } Console.WriteLine("Raising signal..."); // raise(signalToTest); double y = 0.0; double x = 1.0 / y; Console.WriteLine(x); } Console.WriteLine("Done"); } public static void Main(string[] args) { Console.WriteLine("Main thread : " + GetCurrentThreadInfo()); // Create a new thread to show that raise runs the handler on the thread raise is called // from, not necessarily on the main thread Thread thread = new Thread(new ThreadStart(RunTest)); thread.Start(); thread.Join(); } }