C#
SIGINT
Ctrl+C
console app
signal handling

How do I trap CtrlC SIGINT in a C console app?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In a C# console application, the normal way to react to Ctrl+C is Console.CancelKeyPress. That event lets you intercept the interrupt request, run cleanup logic, and optionally prevent immediate termination while the application shuts down in an orderly way.

The Basic Event Handler

The simplest version subscribes to Console.CancelKeyPress and sets a flag when the user presses Ctrl+C.

csharp
1using System;
2using System.Threading;
3
4class Program
5{
6    private static volatile bool _stopRequested;
7
8    static void Main()
9    {
10        Console.CancelKeyPress += OnCancelKeyPress;
11
12        while (!_stopRequested)
13        {
14            Console.WriteLine("Working...");
15            Thread.Sleep(1000);
16        }
17
18        Console.WriteLine("Cleanup complete.");
19    }
20
21    private static void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e)
22    {
23        Console.WriteLine("Ctrl+C received. Stopping gracefully...");
24        e.Cancel = true;
25        _stopRequested = true;
26    }
27}

Setting e.Cancel = true tells the runtime not to terminate the process immediately. That gives your loop time to finish current work and exit cleanly.

Why This Is Better Than Abrupt Exit

A console process may be writing files, flushing logs, holding network connections, or processing background work. If the process dies instantly, data can be left in a bad state.

Handling Ctrl+C gives you a controlled shutdown path. That usually means:

  • stop accepting new work
  • signal long-running operations to cancel
  • wait for cleanup to complete
  • exit with a sensible status code

A Better Pattern With CancellationTokenSource

For modern async or multi-component applications, a cancellation token is often cleaner than a single shared boolean.

csharp
1using System;
2using System.Threading;
3using System.Threading.Tasks;
4
5class Program
6{
7    static async Task Main()
8    {
9        using var cts = new CancellationTokenSource();
10
11        Console.CancelKeyPress += (_, e) =>
12        {
13            Console.WriteLine("Ctrl+C received.");
14            e.Cancel = true;
15            cts.Cancel();
16        };
17
18        try
19        {
20            await RunAsync(cts.Token);
21        }
22        catch (OperationCanceledException)
23        {
24            Console.WriteLine("Canceled cleanly.");
25        }
26    }
27
28    static async Task RunAsync(CancellationToken token)
29    {
30        while (true)
31        {
32            token.ThrowIfCancellationRequested();
33            Console.WriteLine("Processing...");
34            await Task.Delay(1000, token);
35        }
36    }
37}

This scales better because any operation that accepts a token can participate in shutdown without needing to know about console events directly.

SIGINT Versus Platform Details

On Unix-like systems, Ctrl+C maps closely to SIGINT. In .NET, you usually do not handle the raw POSIX signal yourself for a normal console app. Console.CancelKeyPress provides the cross-platform abstraction you actually want.

That makes the code more portable than relying on platform-specific signal APIs unless you truly need lower-level behavior.

When Not to Set e.Cancel = true

If your application does not need graceful shutdown, you can handle the event for logging and still allow the process to terminate by leaving e.Cancel as false. But if you need to release resources or stop background work carefully, set it to true and exit deliberately.

Just remember that setting e.Cancel = true means you are now responsible for making the process end. If your cleanup path hangs forever, the process will keep running.

Common Pitfalls

The biggest pitfall is handling Console.CancelKeyPress but forgetting to stop the main loop. Once you cancel default termination, the program must have its own exit path.

Another mistake is doing too much work directly inside the event handler. The handler should signal shutdown, not perform large blocking operations itself.

Developers also forget that background tasks need cancellation support. Catching Ctrl+C is not enough if worker operations ignore the shutdown signal.

Finally, do not confuse C# console handling with low-level native signal handling. In typical .NET code, Console.CancelKeyPress is the right abstraction.

Summary

  • In C# console apps, Console.CancelKeyPress is the standard way to trap Ctrl+C.
  • Set e.Cancel = true if you need time for graceful shutdown and cleanup.
  • Use a shared flag or, better, a CancellationTokenSource to notify the rest of the application.
  • Keep the event handler small and let the main execution flow perform the actual shutdown.
  • If you suppress default termination, make sure the program can still exit on its own.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.