[issue26189] Interpreter returns control to cmd.exe early
Eryk Sun
report at bugs.python.org
Mon Jan 25 23:23:21 EST 2016
Eryk Sun added the comment:
> An .lnk is launched with ShellExecute which returns control
> immediately upon successful launch
cmd calls ShellExecuteEx, not ShellExecute, and it uses the flags SEE_MASK_NO_CONSOLE (0x8000, don't create a new console) and SEE_MASK_NOCLOSEPROCESS (0x0040, return a process handle if possible).
Here's a walk-through with a debugger attached to cmd while executing a LNK shortcut to "C:\Program Files\Python27\python.exe":
C:\Temp>.\python.lnk -c "import sys,time;time.sleep(60);sys.exit(42)"
Breakpoint 0 hit
SHELL32!ShellExecuteExW:
00007ff9`a5710e20 48895c2408 mov qword ptr [rsp+8],rbx
ss:000000a3`eb3af3a0=000000a3eb597ca0
0:000> ; as /x info @rcx
0:000> ; as /x sz @@(*((unsigned long *)${info}))
0:000> bd 2,3,4; pt; be 2,3,4
ShellExecuteEx returns the process handle:
0:000> ?? *((void **)(${info} + ${sz} - 8)); * hProcess
void * 0x00000000`000002fc
0:000> !handle 2fc
Handle 2fc
Type Process
0:000> g
cmd uses the handle to read the ImageSubsystem type from the process environment block (PEB), for which 3 is a console process and 2 is a GUI process.
Breakpoint 1 hit
cmd!GetProcessSubsystemType:
00007ff7`a133faf4 48895c2410 mov qword ptr [rsp+10h],rbx
ss:000000a3`eb3af458=000000a3eb585640
0:000> g
Breakpoint 2 hit
KERNELBASE!ReadProcessMemory:
00007ff9`a49ac230 4883ec48 sub rsp,48h
0:000> as /x buf @r8
0:000> pt
KERNELBASE!ReadProcessMemory+0x2b:
00007ff9`a49ac25b c3 ret
0:000> ?? ((ntdll!_PEB *)${buf})->ImageSubsystem
unsigned long 3
0:000> g
Since it's a console process, cmd waits and queries the exit code.
Breakpoint 3 hit
KERNELBASE!WaitForSingleObject:
00007ff9`a49840c0 4533c0 xor r8d,r8d
0:000> r rcx
rcx=00000000000002fc
0:000> g
Breakpoint 4 hit
KERNELBASE!GetExitCodeProcess:
00007ff9`a49c46d0 4053 push rbx
0:000> as /x rc @rdx
0:000> pt
KERNELBASE!GetExitCodeProcess+0x3a:
00007ff9`a49c470a c3 ret
0:000> ?? *((unsigned long *)${rc})
unsigned long 0x2a
0:000> ? 0x2a
Evaluate expression: 42 = 00000000`0000002a
It sets the exit code in the 'hidden' environment variable "=ExitCode" as a unsigned hexadecimal number.
C:\Temp>echo %=ExitCode%
0000002A
You can also query the signed value using the pseudo environment variable "errorlevel".
C:\Temp>echo %errorlevel%
42
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue26189>
_______________________________________
More information about the Python-bugs-list
mailing list