1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

OT: Windows 7 failure

Discussion in 'Support' started by Jim Cook, Jul 21, 2010.

  1. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    This is off topic. I posted a question in
    http://stackoverflow.com/questions/3294947/why-cant-i-test-the-return-code-in-windows-7
    that
    is not getting answered, so I hoped to see if somebody here knew.

    I am seeing this problem when running pure cmd, so I do not think that
    simply having TCC installed is part of the problem.

    I reduced the problem further from the stackoverflow posting. Given this
    program (named level250.c for the batch file below):

    #include "windows.h"
    static unsigned __stdcall TestThread(void * unused)
    {
    return 0;
    }

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
    lpszCmdLine, int nCmdShow)
    {
    CreateThread(NULL, 0, TestThread, NULL, 0, NULL);
    ExitProcess(250);
    }

    I compile with "cl /MT level250.c"

    I would expect the errorlevel to be 250 always. I have access to exactly two
    Windows 7 machines and both of them fail after a few thousand iterations. My
    test batch file is:

    @ECHO OFF
    SET I=0
    :pass
    SET /A I=I+1
    Title %I%
    start/wait level250
    if errorlevel 251 goto fail
    if errorlevel 250 goto pass
    :fail


    This runs hundreds of thousands of times on XP boxes, and we have never seen
    a failure on any of the Windows we've used until Windows 7, where it fails.
    It's causing a fair amount of trouble for us, not being able to rely on the
    return code.

    Does anyone have a clue about what is going wrong?

    Thanks in advance.
    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  2. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,177
    Likes Received:
    11
    Jim,

    Does the issue still occur if you remove the second thread? I.e. Just
    call ExitProcess() from WinMain() and not both CreateThread() and
    ExitProcess().

    Are you running on a multicore CPU? I know that one of the changes in
    Win7 was related to an OS mutex. There used to be a single mutex that the
    kernel used. That slowed things down for systems with more than 4 cores.
    So they created multiple mutexes for various parts of the OS and that led
    to a huge performance increase. My guess is that the process object is
    becoming signaled and your calling process wakes up before the exit code
    is fully propagated.

    Check to see if the return code is 259 (STILL_ACTIVE). If it is, then
    adding a small delay between your start/wait and if errorlevel might be
    all you need.

    -Scott

    Jim Cook <> wrote on 07/21/2010 09:55:54 AM:


    two

    iterations. My

    seen

    fails.

    the

     
  3. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    Thanks for your time and suggestions.

    Removing the second thread removes the problem. Of course, this is a data
    point but not a solution for our actual application that has hundreds of
    threads.

    The two machines I tested were both multicore. The actual application
    threads vary; some exit, some do not.

    I'll try the delay tactic. Without the delay, using ExitProcess, exit(), and
    returning 250 from WinMain all fail.

    On Wed, Jul 21, 2010 at 8:38 AM, samintz <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  4. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    The delay did not help.

    On Wed, Jul 21, 2010 at 8:52 AM, Jim Cook <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  5. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,177
    Likes Received:
    11
    Is the return code 259 in the failure case?
    -Scott

    Jim Cook <> wrote on 07/21/2010 12:19:40 PM:


    data

    of

    exit(),

    Just

    in

    that the

    cores.

    that led

    is

    code

    then

    be

    that

    Given

    LPSTR

    never

    it

    rely on

    11/7.

     
  6. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    I believe the return code is 0 in this test. I think it is coming from the
    return value of the thread.

    On Wed, Jul 21, 2010 at 9:33 AM, samintz <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  7. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,177
    Likes Received:
    11
    Sounds like a Windows bug to me...

    Actually, now that I think about it, it kind of makes sense that a delay
    wouldn't work. The calling process would wake up when the process handle
    becomes signaled and grab the exit code and put the value in errorlevel.
    If the exit code changes at some later point it's already too late.

    I think you need some other mechanism to indicate a return code. Writing
    to a disk file or the registry are alternatives. Or create your own
    version of START /WAIT.

    Rex - if the process handle gets signaled and GetExitCodeProcess() returns
    259 (STILL_ACTIVE) do you do any special handling?

    -Scott


    Jim Cook <> wrote on 07/21/2010 12:19:40 PM:


    data

    of

    exit(),

    Just

    in

    that the

    cores.

    that led

    is

    code

    then

    be

    that

    Given

    LPSTR

    never

    it

    rely on

    11/7.

     
  8. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,177
    Likes Received:
    11
    Add
    echo errorlevel = %?
    to be sure.

    And modify your thread return code to something besides 0 to see if it is
    returning the threads return code.

    -Scott

    Jim Cook <> wrote on 07/21/2010 12:45:48 PM:


    the

    a

    hundreds

    application

    and

    changes

    4

    object

    exit

    is,

    might

    http://stackoverflow.com/questions/3294947/why-cant-i-test-the-

    knew.

    think

    hPrevInstance,

    to

    have

    where

    to

    11/7.

     
  9. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    On Wed, 21 Jul 2010 09:55:58 -0400, Jim Cook <>
    wrote:

    |int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
    |lpszCmdLine, int nCmdShow)
    | {
    | CreateThread(NULL, 0, TestThread, NULL, 0, NULL);
    | ExitProcess(250);
    | }

    What if you simply return(250); from WinMain().
     
  10. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    return(250) and exit(250) and ExitProcess(250) all behave identically; they
    fail.

    On Wed, Jul 21, 2010 at 10:35 AM, vefatica <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  11. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    Unless you meant to ask what happens when I do not start a second thread. If
    I do not start a second thread the problem does not arise.

    On Wed, Jul 21, 2010 at 10:41 AM, Jim Cook <jimrcook@gmail.com> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  12. Stephen Howe

    Joined:
    Jun 7, 2008
    Messages:
    127
    Likes Received:
    0
    Yes. I think you should be using _beginthread() or _beginthreadex() and not CreateThread(). You are expecting VC++'s thread support which you are invoking, by compiling with /MT to somehow be aware of what you are doing when you call CreateThread(). _beginthread()/_beginthreadex() also calls CreateThread() but more importantly it does some neccessary bookkeeping, so that RTL is aware of the fact that other threads have started.

    When you quit out from WinMain(), the RTL is not aware that another thread is running and the 2nd thead interferes with clean shutting down. Now if you had used _beginthread()/_beginthreadex(), on exiting WinMain, the RTL sees from the bookkeeping that other threads are running and cleanly shuts down before returning 250.

    Stephen Howe
     
  13. Stephen Howe

    Joined:
    Jun 7, 2008
    Messages:
    127
    Likes Received:
    0
    As a further comment, check out

    http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx
    http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx

    At the bottom of the second web page, it says

    Stephen Howe
     
  14. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    Thank you, Stephen. When I changed to using _beginthread the failure still
    happens just the same.


    On Wed, Jul 21, 2010 at 11:44 AM, Stephen Howe <>wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  15. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    On Wed, 21 Jul 2010 15:35:52 -0400, Jim Cook <>
    wrote:

    |Thank you, Stephen. When I changed to using _beginthread the failure still
    |happens just the same.

    For the sake of testing, and to possibly tell if it's Windows or "C",
    try avoiding the "C" library altogether:

    Link with /ENTRY:"MyMain"

    Code:
    #include <windows.h>
    
    DWORD WINAPI TestThread(LPVOID pv)
    {
    return 0;
    }
     
    INT WINAPI MyMain(VOID)
    {
    	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestThread,
    		NULL, 0, NULL);
    	ExitProcess(250);
    }
     
  16. Rod Savard

    Joined:
    May 26, 2008
    Messages:
    480
    Likes Received:
    3
    I know this doesn't help, but I compiled your code using Borland Delphi and it runs just fine on Win7... went through 10,000 iterations before I stopped it.
     
  17. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    Rod: Is your computer multi-core or single-core?

    On Wed, Jul 21, 2010 at 1:56 PM, Rod Savard <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  18. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    I needed a couple more switches. I hope these were right:
    cl level250.c /link /entry:MyMain /SubSystem:Windows kernel32.lib

    It still failed with your suggested code.

    On Wed, Jul 21, 2010 at 1:54 PM, vefatica <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  19. Rod Savard

    Joined:
    May 26, 2008
    Messages:
    480
    Likes Received:
    3
    Multi.... core 2 duo
     
  20. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    Thanks, Rod. I did have a couple tests that made almost 30K iterations,
    depending on ... something :)

    Is Borland Delphi available somewhere for a free download / trial?

    On Wed, Jul 21, 2010 at 2:56 PM, Rod Savard <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  21. Rod Savard

    Joined:
    May 26, 2008
    Messages:
    480
    Likes Received:
    3
    I believe a trial version is available, but it is a Pascal-based language, not C/C++. The full RAD Studio product does have a C++ compiler, you might check it out. It's an Embarcadero product now, not Borland (I still call it Borland out of habit).
     
  22. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    On Wed, 21 Jul 2010 17:55:28 -0400, Jim Cook <>
    wrote:

    |I needed a couple more switches. I hope these were right:
    |cl level250.c /link /entry:MyMain /SubSystem:Windows kernel32.lib
    |
    |It still failed with your suggested code.

    Did you get a tiny little EXE? Mine was 2560 bytes (no debug info, no
    manifest), a good indication that there's no "C" library stuff in it.
     
  23. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    On Wed, 21 Jul 2010 17:55:28 -0400, Jim Cook <>
    wrote:

    |I needed a couple more switches. I hope these were right:
    |cl level250.c /link /entry:MyMain /SubSystem:Windows kernel32.lib
    |
    |It still failed with your suggested code.

    If you want to try mine (built with VC9) grab

    ftp://lucky.syr.edu/test.zip

    (containing test.exe).
     
  24. Jim Cook

    Joined:
    May 20, 2008
    Messages:
    605
    Likes Received:
    0
    I downloaded and tried your test.exe. It failed after some 30K cycles.

    On Wed, Jul 21, 2010 at 5:22 PM, vefatica <> wrote:




    --
    Jim Cook
    2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
    Next year they're Monday.
     
  25. Rod Savard

    Joined:
    May 26, 2008
    Messages:
    480
    Likes Received:
    3
    I'm trying his test.exe and so far I've hit 80K cycles without a failure. Weird.
     

Share This Page