Почему я не могу проверить код возврата в Windows 7? - PullRequest
5 голосов
/ 21 июля 2010

У меня очень сложная программа, которая дает сбой, и я упростил ее до этого набора тестов с помощью пакетного файла и программы на Си.

Моя программа на C использует ExitProcess для передачи уровня ошибки в пакетфайл.Иногда в Windows 7 (Microsoft Windows [Версия 6.1.7600]) уровень ошибки интерпретируется неправильно.

Я думаю, что это должно работать вечно.В Windows XP он работает вечно.На двух разных двухъядерных компьютерах с Windows 7 (одна 64-битная, одна 32-битная) происходит сбой в течение пары минут.

Не могу себе представить, что я делаю что-то не так, но в случае, если естьчто-то смешное в ExitProcess на Windows 7, я подумал, что спросить.Есть ли здесь что-нибудь, что я сделал незаконно?

Пакетный файл test.bat для cmd.exe:

@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

Уровень программы 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);
    }

МойВерсия и вызов компилятора:

32-разрядная версия оптимизирующего C / C ++ компилятора Microsoft (R) 12.00.8804 для 80x86

Copyright (C) Microsoft Corp 1984-1998.Все права защищены.

cl / MT level250.c

Другая информация: Я также пробовал работать под TCC JPSoft и получить то же поведение, что и при использовании CMD.Я использую прямую программу .c, а не .cpp.Я не вижу сбоев в однопоточной версии.Я поставил исходники и двоичные файлы на http://jcook.info/win7fail, а zip-файл MD5 - это 579F4FB15FC7C1EA454E30FDEF97C16B, а CRC32 - это C27CB73D.

EDIT После предложений я еще больше изменил контрольный пример и все ещеувидеть неудачи.В нашем реальном приложении есть сотни потоков.Некоторые потоки завершаются с различными значимыми кодами возврата, некоторые работают вечно, а некоторые зависают в вызовах или библиотеках операционной системы, и их трудно (если не невозможно) убить.

#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);
    }

Ответы [ 2 ]

1 голос
/ 21 июля 2010

Кажется, что он возвращает результат потока в те времена, когда он выходит из строя. Я изменил возвращаемое значение потока на 37 и добавил echo %errorlevel% в конец пакетного файла. Когда он остановился на моем компьютере, он напечатал 37. Таким образом, кажется, что есть какая-то проблема синхронизации. Чтобы исправить это, я изменил код в main на следующий:

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

В документации для ExitProcess четко сказано, что код выхода "для процесса и всех потоков". Так что может показаться, что есть ошибка, однако полагаться на ExitProcess для уничтожения всех потоков - не самый лучший план. Поэтому ожидание их завершения, вероятно, разумный курс действий.

Я собрал программу и воспроизвел проблему с VC6 (версией, которую вы использовали), VS2005 и VS2008. Я из любопытства запустил его на 2-ядерном ноутбуке win7 и 4-ядерном настольном компьютере win7. Он не воспроизводился на более старом одноядерном компьютере с многопоточным процессором XP, но это не значит, что в конечном итоге он не выйдет из строя; может быть, нужно просто побежать там дольше.

Редактировать Это было бы немного клуджем, но, возможно, обходной путь - сохранить код выхода в глобальной переменной в приложении и вернуть это значение из всех потоков. Тогда в ситуации, когда возникает эта проблема / ошибка, код завершения приложения все равно будет иметь желаемое значение.

1 голос
/ 21 июля 2010

Выведите, что код возврата на самом деле .Нет гарантии, что если что-то пойдет не так, вы получите ожидаемые 251 и 250, например, из-за ошибки сегментации или других ошибок, о которых вы не знаете.Кроме того, я не вижу, куда вы возвращаете 251 в вашем коде.Остерегайтесь высоких кодов выхода, я считаю, что 255 - это безопасный переносимый предел, в некоторых системах он может быть меньше 64 или <= 127. (Это может быть неуместно, поскольку вы, очевидно, используете Windows, но это стоит отметить).1003 * <p>Также попробуйте вызвать отладчик или загрузить дамп ядра при неожиданной смерти процесса.

...