Tengo un programa muy complicado que está fallando, y lo he simplificado para este conjunto de prueba con un archivo por lotes y un programa C.¿Por qué no puedo probar el código de retorno en Windows 7?
Mi programa C usa ExitProcess para devolver el errorlevel a un archivo por lotes. En ocasiones, en Windows 7 (Microsoft Windows [Versión 6.1.7600]), el nivel de error no se interpreta correctamente.
Creo que esto debería funcionar para siempre. En Windows XP, parece ejecutarse para siempre. En dos máquinas diferentes de Windows 7 de doble núcleo (una de 64 bits y otra de 32 bits) falla en un par de minutos.
No me puedo imaginar que estoy haciendo algo mal, pero en caso de que haya algo gracioso sobre ExitProcess en Windows 7, pensé en preguntar. ¿Hay algo aquí que he hecho ilegalmente?
por lotes de archivos test.bat para 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
Programa level250.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);
}
Mi versión del compilador y la invocación son:
Microsoft (R) Versión del compilador de optimización C/C++ 32-bit 12.00.8804 para 80x86
Copyright (C) Microsoft Corp 1984-1998. Todos los derechos reservados.
cl level250.c/MT
Información adicional: También he intentado correr bajo TCC de JPSoft y obtener el mismo comportamiento que el uso de CMD. Estoy usando un programa .c directo, no .cpp. No veo fallas en una sola versión con hilos. Puse las fuentes y los binarios en http://jcook.info/win7fail y el archivo zip MD5 es 579F4FB15FC7C1EA454E30FDEF97C16B y CRC32 es C27CB73D.
EDIT Después de las sugerencias, he cambiado aún más el caso de prueba y todavía veo los fallos. En nuestra aplicación real, hay cientos de hilos. Algunos subprocesos salen con varios códigos de retorno significativos, algunos se ejecutan para siempre, y otros se cuelgan en llamadas al sistema operativo o DLL y son difíciles (si no imposibles) de matar.
#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);
}
¿No debería estar esperando la unión de su hilo una vez que se completa antes de llamar a ExitProcess()? – IanNorton
Debería utilizar WaitForSingleObject() en lugar de un bucle ocupado para esperar la terminación de la secuencia. Además, simplemente devuelva 250 desde WinMain() en lugar de llamar a ExitProcess() directamente. El código de inicio del compilador llamará a ExitProcess() después de que salga WinMain(). –
@IanNorton: no creo que sea necesario esperar a que los hilos terminen y/o se unan. Nuestro programa completo tiene algunos subprocesos que no pueden finalizar, ya sea debido a llamadas de sistema o E/S bloqueadas u otras razones. ¿Hay alguna documentación de Microsoft a la que me puede dirigir que muestre los requisitos para volver a unir los hilos? @Remy: Nuestro programa real es mucho más complicado y hay una razón para la prueba directa. Como resultado, eliminar toda mención de la variable Terminate no resuelve el problema. Es decir, un hilo que simplemente retorna y un WinMain que crea el hilo y luego sale también falla. – piCookie