Kill fgets thread in mingw and wine
我有这个程序。cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #include <windows.h> DWORD WINAPI separateThread(LPVOID) { printf("thread waiting user input\ "); char str[128]; fgets(str, 128, stdin); printf("fgets END ..."); } int main() { printf("program start autokill after 5sec\ "); DWORD tid; HANDLE tha =CreateThread(0,0, separateThread, 0,0,&tid); Sleep(5000); // XXXXXXXX what to put here to Kill fgets-callin-thread ??????????? } |
在Linux上使用以下命令编译:
1 | i686-w64-mingw32-gcc program.cpp |
并运行:
1 | wine a.exe |
...,我希望它本身可以结束,而无需任何用户输入。但是总会有err:ntdll:RtlpWaitForCriticalSection女巫阻止所有内容。
我应该在XXXXX地方放什么?
无济于事的解决方案:
TerminateThread(tha,0),ExitProcess(0),reopen(stdin),fclose(stdin)...通过kbhit-getch组合实现自己的\\'my_gets \\'函数是xp,win7和win8目标的好解决方案,但kbhit在WINE中不起作用。
终止线程几乎永远都不安全。它可能会使事物处于不一致的破碎状态。
例如考虑一个在内存分配中途结束的线程。线程锁定了用于同步访问堆的互斥锁。如果突然终止,线程将无法释放该锁。任何随后的分配内存的尝试都将挂起。
一种可能的解决方案是终止整个过程(terminateprocess函数)。这将导致所有线程被终止并且进程退出而不执行任何清理。例如,这意味着不会清除stdout,不会像任何C析构函数那样运行已注册的atexit处理程序。但是,操作系统级别的资源(例如打开的文件和内存)将被正确释放。
也有exitprocess来执行有序的进程关闭。它执行清除操作,但由于线程突然终止而遭受损坏的全局状态(考虑在清除过程中调用free(),如果堆损坏则挂起)。
旁注。使用_beginthread代替CreateThread可以在新线程中正确初始化c运行时库。
TerminateThread仅在所有情况下都能杀死fget。
但是我最后使用的最干净的解决方案是将输入发送到stdin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void sendEnterToStdin() { INPUT_RECORD ir[2]; for (int i=0; i<2; i++) { KEY_EVENT_RECORD *kev =&ir[i].Event.KeyEvent; ir[i].EventType =KEY_EVENT; kev->bKeyDown = i==0; //<-true, than false kev->dwControlKeyState = 0; kev->wRepeatCount = 1; kev->uChar.UnicodeChar = VK_RETURN; kev->wVirtualKeyCode = VK_RETURN; kev->wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC); } DWORD dw; WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ir, 2, &dw); } |
...并使其适用于WINE:
1 | using ' $ wineconsole --backend=curses a.exe ' instead of ' $ wine a.exe ' |