Skip to content

proposal: x/sys/windows/svc: Call AllocConsole as part of Run #72884

Open
@mediocregopher

Description

@mediocregopher

Proposal Details

Background

I am implementing a windows service which act as a kind of process manager; based on user input during its lifetime the service process will spawn its own child processes (with the CREATE_NEW_PROCESS_GROUP flag set), and based on other user input the service may decide to shut down those child processes using windows.GenerateConsoleCtrlEvent(syscall.CTRL_BREAK_EVENT, pid). This control event acts more or less like a SIGINT in windows world.

When running the process as an actual service, via the Windows Service Manager, I use svc.Run to make all the necessary system calls and process control messages.

When running the service from console the GenerateConsoleCtrlEvent works fine. However, when being run as a service, the GenerateConsolCtrlEvent returns the error The handle is invalid.. This is apparently because when running a process as a service windows does not allocate a console for the process.

Adding the following into my Handler's Execute method fixes the problem:

if r, _, err := windows.NewLazySystemDLL("kernel32.dll").NewProc("AllocConsole").Call(); r == 0 {
	panic(err)
}

Loading the DLL manually is necessary because AllocConsole is not exposed via x/sys/windows.

I discovered that AllocConsole would solve this issue based on this 20 year old thread from CodeGuru.

Proposal

I propose that svc.Run should call AllocConsole itself, perhaps just after the call to RegisterServiceCtrlHandlerEx. I am not a professional windows developer so I could well be mistaken, but I don't believe there's any reason to not allocate a console, and doing so would save other users from having to dig up this odd requirement in the future.

If there is a reason why someone would not want their service to have a console attached then perhaps a new function, RunOpt, could be introduced to the package. Something like:

type RunOpts struct {
    AllocConsole bool
}

func RunOpt(name string, handler Handler, opts RunOpts) error

The AllocConsole field could specifically document why a console allocation would be desired, which would expose this possible edge-case to the user.

Secondary Proposal: Expose AllocConsole in x/sys/windows

I don't know what the process is for adding new syscalls to x/sys/windows, but having AllocConsole exposed there would be convenient.

Metadata

Metadata

Assignees

No one assigned

    Labels

    LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolOS-WindowsProposal

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions