关于C#:Kill fgets加入mingw和wine

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 '