Why can't I check the return code in Windows 7?

I have a very complicated program that fails, and I simplified it for this test suite using a batch file and C.

My C uses ExitProcess to return the error level to a batch file. Sometimes in Windows 7 (Microsoft Windows [Version 6.1.7600]) the error level is misinterpreted.

I think this should go on forever. On Windows XP, it works forever. On two different dual-core Windows 7 machines (one 64-bit 32-bit), it crashes after a couple of minutes.

I can’t imagine that I am doing something wrong, but if there is something funny in ExTProcess on Windows 7, I thought I would ask. Is there anything here that I did illegally?

Batch file test.bat for cmd.exe:

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

Program Level 250.c:

 #include "windows.h" static volatile int Terminate = 0; static unsigned __stdcall TestThread(void * unused) { Terminate = 1; return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { CreateThread(NULL, 0, TestThread, NULL, 0, NULL); while (Terminate == 0) Sleep(1); ExitProcess(250); } 

My version and compiler call are:

Microsoft (R) 32-bit C / C ++ Compiler Optimization version 12.00.8804 for 80x86

Copyright (C) Microsoft Corp. 1984-1998. All rights reserved.

cl / MT level250.c

Other information: I also tried working under JPSoft TCC and getting the same behavior as using CMD. I use the direct .c program, not .cpp. I do not see failures in one version with a thread. I put the sources and binaries in http://jcook.info/win7fail and the MD5 zip file is 579F4FB15FC7C1EA454E30FDEF97C16B and the CRC32 is C27CB73D.

EDIT After making suggestions, I still changed the test case and still see the failures. There are hundreds of threads in our real application. Some threads come out with various important return codes, some run forever, and some of them freeze on operating systems or DLLs and are difficult (if not impossible) to kill.

 #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); return(250); } 
+5
source share
2 answers

Print the return code actually . There is no guarantee that if something goes wrong, you will receive the expected 251 and 250, for example, through a segmentation error or other errors that you are not aware of. Also, I don't see where you are returning 251 code in your code. Be careful with high exit codes, I think 255 is a safe portable limit, on some systems it can be less than 64, or <= 127. (This may not matter since you are obviously using Windows, but it's worth noting. )

Also try calling the debugger or load a kernel dump if the process terminates unexpectedly.

+1
source

It seems to return the result of the thread at the moments when it fails. I changed the return value of the stream to 37 and added echo %errorlevel% to the end of the batch file. When he stopped on my PC, he typed 37. It seems that there is some kind of synchronization problem. To fix this, I changed the code mainly to the following:

 HANDLE h = CreateThread(NULL, 0, TestThread, NULL, 0, NULL); while (Terminate == 0) Sleep(1); WaitForSingleObject( h, INFINITE ); ExitProcess(250); 

The documentation for ExitProcess clearly states that the exit code is "for the process and all threads." So it seems like there is an error, however, relying on ExitProcess to kill all the threads doesn't seem like a better plan. Therefore, waiting for their completion is probably a reasonable course of action.

I built the program and reproduced the problem with VC6 (the version you used, I suppose), VS2005 and VS2008. I ran out of curiosity to a win7 dual-core laptop and a win7 quad-core desktop machine. It did not play on the older XP single-core hyper-threading machine, but this does not mean that it will not fail in the end; perhaps he just needed to work longer.

Change This will be a bit kludge, but perhaps a workaround would be to save the exit code in a global variable in the application and return this value from all threads. Then, in a situation where this problem / error occurs, the application termination code will still be the desired value.

+1
source

Source: https://habr.com/ru/post/981839/


All Articles