News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Win10 may suppress return codes(RC) from MASM 32bit console programs

Started by MtheK, August 08, 2015, 06:53:24 AM

Previous topic - Next topic

adeyblue

If ExitProcess isn't used, the exit code of the process is the exit code of the last thread to exit. If you're not creating a thread yourself, then probably one of the functions you call is now creating one or starting the threadpool in Win10 when it didn't in previous versions.

That you sometimes get the return value you expect and sometimes don't suggests a race condition between which thread exits last.

qWord

Quote from: adeyblue on August 22, 2015, 02:48:54 AM
If ExitProcess isn't used, the exit code of the process is the exit code of the last thread to exit.
any reference for that?
MREAL macros - when you need floating point arithmetic while assembling!

Donkey

Interesting problem. Since you're using batch commands the break in the code was most likely at Vista when the way a bat file executes code was changed. I seem to remember that Microsoft was beginning to have executables called from a batch file run in a separate cmd window. Could be that the exit code you're getting is linked to that change. It's been a while since I've even considered using batch files, sloppy things at best, unreliable at worst so I can't be sure, just seem to remember Raymond Chen mentioning it in his blog once long ago.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

MtheK

  Hhhmmm, adeyblue may be on to something.  I think I found the
problem. Of a total of 28 programs, 7 "failed". I noticed that, of
those latter, there was always a long delay.  For BEEP, after it
played the sound, it took about 30sec B 4 the DOS Prompt appeared; in
Win7, it's immediately after. For SLEEP, I noticed that a requested
60sec wait was taking about 90sec.  So, I snap-dumped them both after
waiting a few seconds, and found they were waiting on this:

ntdll!ZwWaitForWorkViaWorkerFactory+0xa

I have no idea what this is, nor what to do about it. None of my
thread(s) were there, tho, when I snapped a normal DSNTODAY run,
my stack entry was not there either:


00000000`0009e5f8 00000000`57e24880 : 000033ee`6519aa07 00000000`0019ea88 000033ee`6519aa17 00000000`00000000 : ntdll!ZwQueryDirectoryFile+0xa
I think this is my FindNextFile.


yet I was able to display my fields which showed I was probably a
third into the run. However, if my own code was running, it shows
up!? To test that, I just JMP'd to the location of that JMP to put it
in a loop; in that case, it showed up? This was B 4 any call to any
WINAPI cmd:


0019ff94 7786a064 7ffde000 273dfc08 00000000 DSNTODAY!mainCRTStartup [DSNTODAY.ASM @ 1695]
0:000:x86> .frame /r 0
eax=0b9a197b ebx=7ffde000 ecx=00401000 edx=00000061 esi=00401000 edi=00401000
                                               / <== there it is
eip=00401000 esp=0019ff84 ebp=0019ff94 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
DSNTODAY!mainCRTStartup:
00401000 90              nop

FAULTING_SOURCE_CODE:
  1692: mainCRTStartup:
  1693: ;       .STARTUP                   ; prime regs properly
  1694:
> 1695:          NOP                       ; x'90'
  1696:
  1697:
  1698:          MOV   EDX,97
  1699:          JMP   mainCRTStartup


  Anyway, from BEEP:


0:000> !uniqstack -v
Processing 3 threads, please wait

.  0  Id: 1894.5fc Suspend: 0 Teb: 00000000`7ffd8000 Unfrozen
      Start: ntdll_77310000!TppWorkerThread (00000000`773445b0)
      Priority: 0  Priority class: 32  Affinity: ff
Child-SP          RetAddr           : Args to Child                                                           : Call Site
00000000`002bea78 00000000`7474833e : 00000000`003ef70c 00000000`00000000 00000000`003efbf4 00000000`00000000 : ntdll!ZwWaitForWorkViaWorkerFactory+0xa
00000000`002bea80 00000000`74747d35 : 00000000`00000000 00000000`7ffd8000 00000000`74748220 00000000`7ffda000 : wow64!whNtWaitForWorkViaWorkerFactory+0x11e
00000000`002beb10 00000000`74731927 : 00000023`77378cac 00000000`00000023 00000000`00574f10 00000000`003efff0 : wow64!Wow64SystemServiceEx+0x175
00000000`002bf3d0 00000000`7474df82 : 00000000`005746a8 00000000`00000000 00000000`00000000 00000000`7ffdf000 : wow64cpu!TurboDispatchJumpAddressEnd+0xb
00000000`002bf480 00000000`7474dea7 : 00000000`00000000 00000000`002bf4d0 00000000`00000000 00000000`002bf820 : wow64!RunCpuSimulation+0x22
00000000`002bf4b0 00007ff9`778efce3 : 00000000`00000000 00000000`7474dd30 00000000`00000000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x177
00000000`002bf750 00007ff9`778efb7e : 00000000`002bf820 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0x10f
00000000`002bf7d0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

Total threads: 3
Duplicate callstacks: 2 (windbg thread #s follow):
1, 2


so this apparently controls the return code since it's (probably) the
last one. I assume some timeout expired and it decided to over-ride,
not save, etc my return code and then supplied the fake rc=0.

---

  On a side note, maybe related, my TESTFK failed to get this command
to work:

         MOV   WAITKILL,77
         INVOKE SystemParametersInfo,
               SPI_GETWAITTOKILLTIMEOUT,     ; x'007A'
               0,
               OFFSET WAITKILL,
               0
         MOV   WTFEAXRC,EAX

which I do dynamically via LoadLibrary/GetProcAddress in a separate
thread since, otherwise, it causes the force-killer to not honor my
allowed shutdown time ("user32.dll") in Win7.  I forced a crash
(INT3) after this call if WAITKILL stayed a 77, and the 'Return
Value' (EAX) is this:

0040c738 02 00 00 c0  = x'C0000002'.

I had to save it in my own DWORD since the stupid WER dump doesn't
seem to show my program on the separate threads' stack (as above):


0:001> !uniqstack -v
Processing 5 threads, please wait

.  0  Id: 14e0.1ce8 Suspend: 0 Teb: 7ffdd000 Unfrozen
      Start: TESTFK!mainCRTStartup (00401000)
00000000                               .CODE
      Priority: 0  Priority class: 32  Affinity: ff
ChildEBP RetAddr  Args to Child
0019ff00 754a13c8 00000000 0019ff44 7b901358 ntdll!ZwDelayExecution+0xc (FPO: [2,0,0])
0019ff68 754a131f 0000000f 00000000 0019ff94 KERNELBASE!SleepEx+0x98 (FPO: [SEH])
0019ff78 00402b45 0000000f 76133744 7ffde000 KERNELBASE!Sleep+0xf (FPO: [Non-Fpo])
0019ff94 7786a064 7ffde000 10d154d3 00000000 TESTFK!mainCRTStartup+0x1b45 [TESTFK.ASM @ 1371]
00001B40  E8 00000000 E   *        call   Sleep
00001B45  EB EA                         JMP   WAITFORIT

0019ffdc 7786a02f ffffffff 7788d7b7 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [Non-Fpo])
0019ffec 00000000 00401000 7ffde000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

.  1  Id: 14e0.d2c Suspend: 0 Teb: 7ffda000 Unfrozen
      Start: TESTFK!mainCRTStartup+0x7519 (00408519)
00007519 LOADAPIX:
      Priority: 0  Priority class: 32  Affinity: ff
ChildEBP RetAddr  Args to Child
0070f358 00000000 77878e8c 778307f8 ffffffff ntdll!ZwGetContextThread+0xc (FPO: [2,0,0])
### WHERE IS MY ENTRY???


### funny that this next is almost what's in BEEP and SLEEP (32bit only?) ###
.  2  Id: 14e0.dc0 Suspend: 0 Teb: 7ffd7000 Unfrozen
      Start: ntdll!TppWorkerThread (778445b0)
      Priority: 0  Priority class: 32  Affinity: ff
ChildEBP RetAddr  Args to Child
0084fdc8 77844836 0000008c 001cf6e0 00000010 ntdll!ZwWaitForWorkViaWorkerFactory+0xc (FPO: [5,0,0])
0084ff80 76133744 001c7c30 76133720 da04c2a6 ntdll!TppWorkerThread+0x286 (FPO: [Non-Fpo])
0084ff94 7786a064 001c7c30 104c54d3 00000000 kernel32!BaseThreadInitThunk+0x24 (FPO: [Non-Fpo])
0084ffdc 7786a02f ffffffff 7788d7b7 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [Non-Fpo])
0084ffec 00000000 778445b0 001c7c30 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

Total threads: 5
Duplicate callstacks: 2 (windbg thread #s follow):
3, 4


yet '!analyze -v' pinpoints my INT3 and knows my stack entry,
but no regs, so I'm obviously OS-aware somehow:


LAST_CONTROL_TRANSFER:  from 76133744 to 00409141

STACK_TEXT:
0070ff80 76133744 0040b000 76133720 daf0c2a6 TESTFK!mainCRTStartup+0x8141 [TESTFK.ASM @ 2695]
0070ff94 7786a064 0040b000 10b854d3 00000000 kernel32!BaseThreadInitThunk+0x24
0070ffdc 7786a02f ffffffff 7788d7b7 00000000 ntdll!__RtlUserThreadStart+0x2f
0070ffec 00000000 00408519 0040b000 00000000 ntdll!_RtlUserThreadStart+0x1b
STACK_COMMAND:  ~1s; .ecxr ; kb

FOLLOWUP_IP:
TESTFK!mainCRTStartup+8141 [TESTFK.ASM @ 2695]
00409141 cc              int     3

FAULTING_SOURCE_CODE:
ABENDRC EQU 3221225474   ; DWORD won't work??? C0000002h
  2691: ;  .if WAITKILL == 77           ; if field not populated...
  2692:          MOV   EAX,ABENDRC
  2693:   .if eax == WTFEAXRC           ;* THIS VIOLATES DOC!!!?? Only rc=0 says error !!!??
  2694: ;*
> 2695:          INT  3
  2696:   .endif

APIADDR4A
0040c43c 60 08 26 75   =   x'75260860' = EBX
WTFEAXRC
0040c738 02 00 00 c0       (EAX immediately after 'call EBX')
WAITKILL
0040c720 4d 00 00 00       (same as what I set it to B 4 call)
WAITKILLRC
0040c72c 00 00 00 00       (from GetLastError anyway)


and so I can't do '.frame /r' to see my regs as I can in Win7!?
Trying .frame "raw" but nothing yet...

This seemingly contradicts the WINAPI doc that says an error gets
eax=0 and you must do GetLastError (I did so anyway, but that was
a 0).  Since EAX is not a 0 (I get a '1' in Win7), my WAITKILL
DWORD should contain the value, but it doesn't (it has 5000 in Win7).
The 2 other requests also failed to update my fields:

SPI_GETWAITTOKILLSERVICETIMEOUT
SPI_GETHUNGAPPTIMEOUT

but I didn't check EAX on those; it's probably the same.

---

Strange...



MtheK

  This smells of a problem like when the mainframe went from 24bit to
31bit addressing. Many app programmers used the top byte for flags,
so when they loaded up all 4 bytes into a register, if that top byte
wasn't 0, it would abend w/an S0C4, which, basically, is a virtual
address w/no valid segment/page table entry, because it was trying to
address, say, x'27xxxxxx' instead of x'00xxxxxx'.

  Perhaps this x'C0000002' is an S0C4 because OS code (ie: sysenter)
isn't clearing the top half of a 64bit register.  Perhaps that's why
my TESTFK cmds fail and are being covered up. Perhaps the same for
that "factory" thread; if its' ECB (mainframe speak again: an Event
Control Block; if bit x'80' isn't a 1, the OS won't run the code)
isn't POSTed, it'll wait forever (tho, even here, some 30sec timeout
must eventually end it and then sets the fake rc=0)...


MtheK

...and I'll state the obvious, in case it's not obvious;
IF the address IS valid, but NOT yours, you've just clobbered
someone else's data! That was fun back then!
That's a DATA INTEGRITY CORRUPTION!

  Since this seems to be in 'sysenter' code (Win7):


detail here:

eax=0000007a ebx=0040c710 ecx=ffffffff edx=006e0174 esi=0000007a edi=00000000
eip=76957e21 esp=0012fa10 ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
USER32!RealSystemParametersInfoA+0x4f9:
76957e21 e80f700000      call    USER32!NtUserSystemParametersInfo (7695ee35)

eax=0000007a ebx=0040c710 ecx=ffffffff edx=006e0174 esi=0000007a edi=00000000
eip=7695ee35 esp=0012fa0c ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
USER32!NtUserSystemParametersInfo:
7695ee35 b853120000      mov     eax,1253h

eax=00001253 ebx=0040c710 ecx=ffffffff edx=006e0174 esi=0000007a edi=00000000
eip=7695ee3a esp=0012fa0c ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
USER32!NtUserSystemParametersInfo+0x5:
7695ee3a ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)

eax=00001253 ebx=0040c710 ecx=ffffffff edx=7ffe0300 esi=0000007a edi=00000000
eip=7695ee3f esp=0012fa0c ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
USER32!NtUserSystemParametersInfo+0xa:
7695ee3f ff12            call    dword ptr [edx]      ds:0023:7ffe0300={ntdll!KiFastSystemCall (776d6340)}
                                             / <== OFFSET (1st 4 bytes) = 7ffe0300 40 63 6d 77      == /

eax=00001253 ebx=0040c710 ecx=ffffffff edx=7ffe0300 esi=0000007a edi=00000000
eip=776d6340 esp=0012fa08 ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
ntdll!KiFastSystemCall:
776d6340 8bd4            mov     edx,esp

##### WAITKILL WAS CHG'D HERE:

eax=00001253 ebx=0040c710 ecx=ffffffff edx=0012fa08 esi=0000007a edi=00000000
eip=776d6342 esp=0012fa08 ebp=0012ff24 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
ntdll!KiFastSystemCall+0x2:
776d6342 0f34            sysenter
                            / <== not traceable (a la SVC?)

0012f9e8 9c 00 00 00 48 fb 12 00 34 fb 12 00 24 fa 12 00 be 56 75 77 00  ....H...4...$....Vuw.
0012f9fd 00 6e 00 00 00 00 00 1a 02 00 00  41 ee 95 76 26 7e 95 76 7a 00  .n.........A..v&~.vz.
0012fa12 00 00 00 00 00 00 10 c7 40 00 00 00 00 00 00 00 00 00 00 00 00  ........@............
0012fa27 00 90 7e 95 76 38 01 6e 00 26 5f 75 77 d7 d6 b8 77 00 00 00 00  ..~.v8.n.&_uw...w....
0012fa3c 00 00 00 00 00 00 6e 00 bc 2d 6e 00 00 00 00 00 00 00 00 00 4c  ......n..-n.........L

.  0  Id: 1438.13a0 Suspend: 1 Teb: 7ffdf000 Unfrozen
      Start: TESTFK!mainCRTStartup (00401000)
      Priority: 0  Priority class: 32  Affinity: 3
ChildEBP RetAddr  Args to Child
0012fa08 76957e26 0000007a 00000000 0040c710 USER32!NtUserSystemParametersInfo+0xc (FPO: [4,0,0])
0012ff24 76957ed0 0000007a 00000000 0040c710 USER32!RealSystemParametersInfoA+0x4fe (FPO: [Non-Fpo])
0012ff6c 00408bbb 0000007a 00000000 0040c710 USER32!SystemParametersInfoA+0x57 (FPO: [Non-Fpo])
0012ff84 00402637 772e1114 7ffd8000 0012ffd4 TESTFK!mainCRTStartup+0x7bbb [TESTFK.ASM @ 2727]
0012ff94 776eb429 7ffd8000 77b8d36f 00000000 TESTFK!mainCRTStartup+0x1637 [TESTFK.ASM @ 1282]
0012ffd4 776eb3fc 00401000 7ffd8000 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
0012ffec 00000000 00401000 7ffd8000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

Total threads: 1


who knows if that address is restricted to just a single process?
Perhaps OSs' own storage could be wiped out (say, MY MISSING STACK
ENTRY)? And who knows where that missing bit (the POSTed ECB) went?
Didn't the Tron guy meet a free "bit"? OK, I'm stretching, but the
possibility is NOT ZERO if this is what's happening...


MtheK

  Hhhmmm...it looks like hutchs' suggestion is good after all,
just w/a slight twist. I combined the best of both worlds.
Let's call it a "conditional ExitProcess"! ON CONDITION OF WIN10!

  In my ABENDXIT thread, just B 4 I decide
"to RET or not; that is the question" (also ExitThread), I count the
# of threads in my process; in Win7, it's a 1 (myself); all my other
threads have already cleaned up and RET'd by this time.  So, if the
# of threads is > 1, I do the ExitProcess over ExitThread (only ABENDXIT
uses this over RET).  Now, the 30-second hang at EOJ is gone, and my DIY
"fix" in the .BAT did NOT detect a fake rc=0, as my correct RC was
detected by the .BAT properly.

  These are my results of my tests. Basically, it shows the TOD and
the # of threads in my process; the hex stuff I didn't show here:

Win7:

2015/08/28 10:43:02.377  0000000001
2015/08/28 10:43:02.392  0000000002
2015/08/28 10:43:03.422  0000000002
...
2015/08/28 10:43:13.328  0000000002
2015/08/28 10:43:14.358  0000000002
then Ctl-C ...
2015/08/28 10:43:15.793  0000000001


Win10:

2015/08/28 12:02:31.687  0000000001
2015/08/28 12:02:31.734  0000000002
2015/08/28 12:02:32.796  0000000005
... (snap dump also taken)
2015/08/28 12:02:48.792  0000000005
2015/08/28 12:02:49.854  0000000005
then Ctl-C ...
2015/08/28 12:02:51.618  0000000004


  For each:

. the 1st record is the initial call to get this #, in my main
thread, B 4 I did any of these weird-ass whatevers that is causing
this Win10 problem.  Obviously, a 1 means I'm the only thread, so
these "factory" things aren't there yet.

. the 2nd record is when I set up and run my next thread to get
this #, that runs every second (a "heartbeat" if you will); this
is its' initial call. A 2 says my main thread exists, and this new
thread of mine exists. Again, this is B 4 the weird-ass whatevers.

. the 3rd record is when the %&^@ hits the fan, but only for Win10!
Somewhere within that heartbeat, probably, these are those "factory"
threads from using these weird-ass whatevers.  They remain until
shutdown, or 60 SECONDS (see below!).

. the last record is from my new code that implements the
"conditional ExitProcess". I have my own 1-second built-in lag from
the Ctl-C,etc (true shutdown can get 5) in this program.  For Win7,
1 means me (ABENDXIT) only. For Win10, that 4 means there are 3
"factory" threads. What I get is the start address of each thread
(ABENDXIT + "foreign"), and the ones that aren't mine are the same
(x'778445b0'); they are what the equivalent snap dump below shows.


  GET THIS!!! These "factory" threads apparently hang around for
60 seconds, then go away:


2015/08/28 11:49:03.086  0000000001
2015/08/28 11:49:03.133  0000000002
2015/08/28 11:49:04.194  0000000005
...
2015/08/28 11:50:02.488  0000000005
2015/08/28 11:50:03.550  0000000002
...
2015/08/28 11:51:02.871  0000000002
2015/08/28 11:51:04.539  0000000001


so perhaps some registry setting can turn this off ("timeout=0"?),

but if I snap it within 60 seconds after using these weird-ass
whatevers, then it matches my count:


Debug session time: Fri Aug 28 12:02:45.000 2015

0:000> !uniqstack -v
Processing 5 threads, please wait

.  0  Id: 1240.2bc0 Suspend: 0 Teb: 00000000`7ffdb000 Unfrozen
      Start: TESTFK!mainCRTStartup (00000000`00401000)
00000000         .CODE
      Priority: 0  Priority class: 32  Affinity: ff
Child-SP          RetAddr           : Args to Child                                                           : Call Site
00000000`0009efd8 00000000`57e11d3d : 00000023`77878f2c 00000000`57e20023 00000000`00000001 00000000`0019fff0 : wow64cpu!CpupSyscallStub+0x2
00000000`0009efe0 00000000`57e2df82 : 00000000`7ffde000 00000000`0009f820 00000000`00000000 00000000`00252398 : wow64cpu!Thunk2ArgNSpNSpReloadState+0xc
00000000`0009f090 00000000`57e2dea7 : 00000000`00000000 00000000`0009f0e0 00000000`00000000 00000000`0009f820 : wow64!RunCpuSimulation+0x22
00000000`0009f0c0 00007ffa`359e05d7 : 00000000`004000c0 00000000`57e2dd30 00000000`7ffdf000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x177
00000000`0009f360 00007ffa`359d4047 : 00000000`00000000 00007ffa`359ddead 00000000`00000001 00000000`00000000 : ntdll!LdrpInitializeProcess+0x17c3
00000000`0009f750 00007ffa`3598fb7e : 00000000`0009f820 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0x44473
00000000`0009f7d0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

.  1  Id: 1240.18a4 Suspend: 0 Teb: 00000000`7ffd8000 Unfrozen
      Start: TESTFK!mainCRTStartup+0xa6b1 (00000000`0040b6b1)
0000A6B1 SHOWTCBX:
      Priority: 0  Priority class: 32  Affinity: ff
Child-SP          RetAddr           : Args to Child                                                           : Call Site
00000000`001ff3c8 00000000`57e11d3d : 00000023`77878cbc 00000000`00000023 00000000`0040e584 00000000`0084fff0 : wow64cpu!CpupSyscallStub+0x2
00000000`001ff3d0 00000000`57e2df82 : 00000000`0040e000 00000000`00000000 00000000`00000000 00000000`7ffdf000 : wow64cpu!Thunk2ArgNSpNSpReloadState+0xc
00000000`001ff480 00000000`57e2dea7 : 00000000`00000000 00000000`001ff4d0 00000000`00000000 00000000`001ff820 : wow64!RunCpuSimulation+0x22
00000000`001ff4b0 00007ffa`3598fce3 : 00000000`00000000 00000000`57e2dd30 00000000`00000000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x177
00000000`001ff750 00007ffa`3598fb7e : 00000000`001ff820 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0x10f
00000000`001ff7d0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

.  2  Id: 1240.2150 Suspend: 0 Teb: 00000000`7fead000 Unfrozen
      Start: ntdll_77810000!TppWorkerThread (00000000`778445b0)
      Priority: 0  Priority class: 32  Affinity: ff
Child-SP          RetAddr           : Args to Child                                                           : Call Site
00000000`0035ea78 00000000`57e2833e : 0000014c`00010000 00000000`00000000 00000000`00a4fbf4 00000000`57e2438c : ntdll!ZwWaitForWorkViaWorkerFactory+0xa
00000000`0035ea80 00000000`57e27d35 : 00000000`00000000 00000000`7fead000 00000000`57e28220 00000000`7feaf000 : wow64!whNtWaitForWorkViaWorkerFactory+0x11e
00000000`0035eb10 00000000`57e11927 : 00000023`77878cac 00000000`00000023 00000000`00654ef0 00000000`00a4fff0 : wow64!Wow64SystemServiceEx+0x175
00000000`0035f3d0 00000000`57e2df82 : 00000000`00654788 00000000`00000000 00000000`00000000 00000000`7ffdf000 : wow64cpu!TurboDispatchJumpAddressEnd+0xb
00000000`0035f480 00000000`57e2dea7 : 00000000`00000000 00000000`0035f4d0 00000000`00000000 00000000`0035f820 : wow64!RunCpuSimulation+0x22
00000000`0035f4b0 00007ffa`3598fce3 : 00000000`00000000 00000000`57e2dd30 00000000`00000000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x177
00000000`0035f750 00007ffa`3598fb7e : 00000000`0035f820 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0x10f
00000000`0035f7d0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

Total threads: 5
Duplicate callstacks: 2 (windbg thread #s follow):
3, 4


AND WORSE, these weird-ass whatevers REPLACED/LOST my own stacks:
.  0  Id: 1240.2bc0 Suspend: 0 Teb: 00000000`7ffdb000 Unfrozen
      Start: TESTFK!mainCRTStartup (00000000`00401000)
.  1  Id: 1240.18a4 Suspend: 0 Teb: 00000000`7ffd8000 Unfrozen
      Start: TESTFK!mainCRTStartup+0xa6b1 (00000000`0040b6b1)

which gives me my IPs in Win7, at least for debugging purposes???!!!
My WinDbg is still Win7, so not really sure what the threads/stacks
are. Perhaps they're buried somewhere, or interpreted differently,
which would mean the .dmps aren't portable across OS versions unless
some keyword or something could be used (mainframe usually can tell
the difference, but sometimes, it had to be told).

  I can't install anything on this Win10 machine, so my options are
limited to what I have available; perhaps others? If so, have fun.

  Also, this doesn't explain those SPI x'C0000002' failures.



MtheK

  It looks like, for simple programs (my BEEP), that have no other
threads of mine, I can just use GetVersionEx (or the lack of it;
Win11?) to decide whether I do a RET or an ExitProcess. For my
ABENDXIT thread, it waits for my other threads to finish (or timeout)
anyway, so it can do the same check; ExitThread (over RET for this
only) or ExitProcess. Since this now controls how I exit, maybe
counting threads isn't needed now (it was sloppy anyway; I don't
see a simple WINAPI cmd to get that for my process?), tho it did
help to nail down when those "factory" threads started, which may
be my 3 SPI "failed" INVOKEs.  Yet BEEP has no SPI calls.
I still don't know the commonality of a quarter of my programs.

  Still, for a normal application program to have to apparently do this
is pretty lousy and s/not have to be needed, just to run on Win10!!!
Am I now expected to clean up THEIR "factory" threads? I can only
imagine what my old store-bought program would do.

  At least, now, my system works almost like it does in Win7, tho I have
to ignore those SPI calls since they produce no data...


jj2007

Quote from: MtheK on August 31, 2015, 08:10:25 AMAm I now expected to clean up THEIR "factory" threads?

No. This is what ExitProcess was designed for.


Donkey

Raymond Chen had this to say for all the "old fashioned model" guys who like to RET from a process.

http://blogs.msdn.com/b/oldnewthing/archive/2010/08/27/10054832.aspx
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

This discussion has made me laugh, it would not matter what you did with ancient mainframes, the termination of a running program is controlled by the operating system, not vague recollections from antiquity.

A cursory glance at the old Win32.HLP file tells you the story.

Quote
The ExitProcess function ends a process and all its threads.

VOID ExitProcess(

    UINT uExitCode    // exit code for all threads 
   );   

Parameters

uExitCode

Specifies the exit code for the process, and for all threads that are terminated as a result of this call. Use the GetExitCodeProcess function to retrieve the process's exit value. Use the GetExitCodeThread function to retrieve a thread's exit value.

Return Values
This function does not return a value.

Remarks
ExitProcess is the preferred method of ending a process. This function provides a clean process shutdown. This includes calling the entry-point function of all attached dynamic-link libraries (DLLs) with a value indicating that the process is detaching from the DLL. If a process terminates by calling TerminateProcess, the DLLs that the process is attached to are not notified of the process termination.

I wonder what the point is in trying to produce a deviant technique for what is a simple and tidy way to terminate a running application.

MtheK

  Thanks for proving my point. W/such a blanket statement, why should
the OS ever fix their faulty code? "Oh, you have multiple, hanging
factory threads, a fake rc=0, and a 30-second lag at termination?
Oh, you don't do ExitProcess? Then it's YOUR fault for not cleaning up
the mess WE made!".  And, of course, this also explains the failure
of the 3 SPI commands, and my missing stacks, since it obviously
knows in advance that I won't be doing an ExitProcess.

  BTW, when you do your ExitProcess in your primary thread, and you
lose data from your SetConsoleCtrlHandler thread, which is the ONLY
thread that keeps the force-killer at bay during a power-off, remember
this discussion.

  I did like Chen's article, especially the "rude" part. Granted,
productional systems probably don't have much assembler, but that's
their loss.

  Seriously tho, thank you adeyblue for your suggestion, which
pointed to these "hanging system-injected" threads.

  No wonder the ancient mainframe remains vastly superior to the PC.
Thanks again for the hearty laugh!