[PATCH 1 of 2] win32: spawndetached returns pid of detached process and not of cmd.exe

Yuya Nishihara yuya at tcha.org
Sun Feb 16 11:12:22 CST 2014


On Sat, 15 Feb 2014 20:09:29 +0100, Simon Heimberg wrote:
> We can attach to a console of a process with AttachConsole(pid). Not 
> sure if the process created by spawndetached always has a console, but 
> at least here it does.
> 
> The code would look similar to this (according to 
> http://stackoverflow.com/a/15281070):
> 
> CTRL_C_EVENT = 0
> def _StopProcess(pid):
>      _check(kernel32.FreeConsole()) # detach from my console
>      # stderr/stdout to console do not work from here!
> 
>      _check(_kernel32.AttachConsole(pid)) # attach to console of pid
>      # disable Ctrl-Chandler
>      _check(kernel32.SetConsoleCtrlHandler(None, True))
> 
>      _check(_kernel32.GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
> 
>      _check(_kernel32.FreeConsole())
>      kernel32.AttachConsole(-1) # reattach to my console
>      # TODO: fix stderr/stdin when they were at the console
> 
>      #ToDo: wait for process to quit
> 
>      # enable Ctrl-C handler
>      _check(kernel32.SetConsoleCtrlHandler(None, False))
> 
> If this is run in a separate process, this simplification seems to work:
> 
> CTRL_C_EVENT = 0
> def _StopProcess(pid):
>      _check(kernel32.FreeConsole()) # detach from my console
>      # stderr/stdout to console do not work now!
> 
>      _check(_kernel32.AttachConsole(pid)) # attach to console of pid
>      # Send Ctrl-C to process (and myself)
>      _check(_kernel32.GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
> 
> When I try to catch the Ctrl-C exception on myself, I fail. The cases 
> "except:" and "except BaseException:" are not executed, only "finally:". 
> So maybe this is also true for the stopped process.
> 
> This only works as expected for processes started by spawndetached (like 
> hg serve -d). When I start multiple serve processes from one console (hg 
> serve&) and tell to stop one pid, all are stopped. (They belong to the 
> same console.)

I see.  Probably because detached processes are executed by cmd.exe, they
have independent consoles, so AttachConsole() can be used.

BTW, I'm trying a slightly different approach for TortoiseHg.

https://bitbucket.org/yuja/hgext-workarounds/src/a9d349575c80/hgext/win32ill.py

Instead of AttachConsole(), it spawns separate thread to listens to WM_CLOSE,
and sends CTRL_C_EVENT to itself.  It worked fine for simple cases, but I don't
think this can be generally used, especially for tests.

> This could be changed by sending CTRL_BREAK to the process group of the 
> PID (CTRL_C can not be sent to a group). But for this we must start the 
> process with process group creation enabled. and CTRL_BREAK could have 
> side-effects.
> 
> New thought. Would it help?

> When creating a service, we set a signal handler in 
> commands.httpservice, which calls _kernel32.ExitProcess on any event 
> (Ctrl-C, Ctrl-Break, Ctrl-Close, ...). Does this do any cleanup? (The 
> handler is win32.set_signal_handler [2].)
> 
> [2] http://selenic.com/repo/hg/file/7648e9aef6ee/mercurial/win32.py#l296

I think it skips cleanup, so it might be useless to try to shutdown "serve -d"
process by Ctrl-C on Windows.

I guess win32.setsignalhandler() exists because blocking winsock calls
cannot be interrupted.

Regards,


More information about the Mercurial-devel mailing list