[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 17:12:22 UTC 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