在 mingw 和 wine 中杀死 fgets 线程

Kill fgets thread in mingw and wine

我有这个 program.cpp :

#include <stdio.h>
#include <windows.h>
DWORD WINAPI separateThread(LPVOID)
{  printf("thread waiting user input\n");
   char str[128]; fgets(str, 128, stdin);
   printf("fgets END ...");
}
int main()
{
   printf("program start autokill after 5sec\n");
   DWORD tid; HANDLE tha =CreateThread(0,0, separateThread, 0,0,&tid);
   Sleep(5000);
  // XXXXXXXX what to put here to Kill fgets-callin-thread ???????????
} 

在 linux 中编译:

i686-w64-mingw32-gcc program.cpp

和运行它与:

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 不会被刷新,注册的 atexit 处理程序不会 运行 以及任何 C++ 析构函数。但是 OS 级资源,如打开的文件和内存将被正确释放。

还有exitprocess来执行有序的进程关闭。它执行清理,但由于线程突然终止而导致全局状态损坏(考虑在清理期间调用 free() ,如果堆已损坏,它会挂起)。

旁注。使用 _beginthread instead of CreateThread 以便在新线程中正确初始化 c 运行time 库。

TerminateThread 只能确保在所有情况下都能杀死 fgets。

但我最后使用的最干净的解决方案是将输入发送到标准输入:

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 :

using ' $ wineconsole --backend=curses a.exe ' instead of ' $ wine a.exe '