Win32 Console Application Unexpectedly Terminates with Code 58

50 Views Asked by At

On my system, the following code (written in Zig, using zigwin32 for bindings to the WinAPI) returns the error code 58 after the spawned console is closed:

const std = @import("std");
const win32 = @import("zigwin32/win32.zig");
const foundation = win32.foundation;
const console = win32.system.console;

// Overrides default behvior, including CTRL_CLOSE_EVENT
fn consoleHandler(_: u32) callconv(.C) foundation.BOOL {
    return 1;
}

pub fn wWinMain(_: foundation.HINSTANCE, _: ?foundation.HINSTANCE, _: [*c]const u16, _: c_int) c_int {
    std.debug.assert(console.AllocConsole() != 0);
    std.debug.assert(console.SetConsoleCtrlHandler(consoleHandler, 1) != 0);

    while (true) {}

    return 0;
}

Can someone please explain to me why this is happening?

In my mind the program should never stop because there is no explicit ExitProcess call and the while loop is never exited from. The only way the program can end, I think, is if the console's events run on a separate thread and close the main thread, returning 58, but I'm not sure why or how this is happening.

1

There are 1 best solutions below

2
Remy Lebeau On BEST ANSWER

In my mind the program should never stop because there is no explicit ExitProcess call

Not by you, no. But there is one, actually. It is being called by the OS.

The only way the program can end, I think, is if the console's events run on a separate thread and close the main thread

That is exactly what happens. Per the HandlerRoutine callback function documentation:

An application-defined function used with the SetConsoleCtrlHandler function. A console process uses this function to handle control signals received by the process. When the signal is received, the system creates a new thread in the process to execute the function.

When a console window is closed, it's list of handlers are called for CTRL_CLOSE_EVENT, and if any return TRUE (as yours does), the process is terminated immediately.

The CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals give the process an opportunity to clean up before termination. A HandlerRoutine can perform any necessary cleanup, then take one of the following actions:

  • Call the ExitProcess function to terminate the process.
  • Return FALSE. If none of the registered handler functions returns TRUE, the default handler terminates the process.
  • Return TRUE. In this case, no other handler functions are called and the system terminates the process.

So, a console handler can't stop its process from being terminated, it can only control whether subsequent handlers are called or not.