Windows NetServerEnum创建赢得';关不上
当我试图解决之前提出的一个问题时,我发现即使没有我的线程,问题也会发生 我现在拥有的是一个非常简单的单线程代码,它调用-Windows NetServerEnum创建赢得';关不上,windows,networking,thread-safety,threadpool,netapi32,Windows,Networking,Thread Safety,Threadpool,Netapi32,当我试图解决之前提出的一个问题时,我发现即使没有我的线程,问题也会发生 我现在拥有的是一个非常简单的单线程代码,它调用-NetServerEnum() . 返回时,它调用NetApiBufferFree()并从main返回,这将结束进程。 此时,我的线程确实结束了,但进程不会退出,因为有4个线程(不是我打开的): 1*ntdll.dll!TplsTimerSet+0x7c0(堆栈位于ntdll.dll!WaitForMultipleObjects) (在调用NetServerEnum()时打开了
NetServerEnum()
. 返回时,它调用NetApiBufferFree()
并从main返回,这将结束进程。
此时,我的线程确实结束了,但进程不会退出,因为有4个线程(不是我打开的):
1*ntdll.dll!TplsTimerSet+0x7c0
(堆栈位于ntdll.dll!WaitForMultipleObjects
)
(在调用NetServerEnum()
时打开了此窗口)
3*ndll.dll!RtValidateHeap+0x170
(堆栈位于ntdll.dll!ZwWaitWorkViaWorkerFactory+0xa
)
(这些在我的代码返回时打开)
更新:
如果我杀死运行ntdll.dll的线程!TplsTimerSet+0x7c0外部(使用process explorer),在返回main()
之前,程序将正常退出。
我想知道可能有用
更新2:(更多技术信息)
我正在使用:
Win7 Enterprise SP1上的MS Visual Studio 2010 Ultimate x64(SP1Rel)
代码是C(但编译为C++开关打开)
子系统:WINDOWS
编译器:cl.exe(使用IDE)
所有其他参数都是默认值
我正在使用一个自我修改的入口点(/entry:“entry”
),它是我程序中唯一的函数):
前面提到的所有测试都是在大约100个单元的windows域网络中进行的
更新3:
在(非虚拟)WinXP 32bit上测试时,不会出现此问题。(同一个二进制文件,不过对于Win7 x64,测试了两个二进制文件-WOW上的32位和本机x64)当您使用自定义入口点时,您绕过了运行库,这意味着您要负责退出进程。如果没有更多线程运行,进程将隐式退出,但正如您所发现的,操作系统可能会代表您创建您无法控制的线程 在您的情况下,只需在
entry()
函数末尾显式调用ExitProcess
int entry(void)
{
SERVER_INFO_101* si;
DWORD a,b;
NET_API_STATUS c;
c = NetServerEnum ( NULL , 101 , (LPBYTE*) &si , MAX_PREFERRED_LENGTH , &b , &a , SV_TYPE_WORKSTATION, NULL , 0 );
c = NetApiBufferFree (si);
Sleep(1000);
ExitProcess(0);
}
在没有调用
ExitProcess
和自定义入口点的情况下,您看到的行为与预期一致。您敢发布测试程序的完整代码吗?对于那些想重现你描述的内容的人来说,这可能很有趣。此外,有关所使用的环境(OS)、编译器和SDK版本的详细信息也会有所帮助。最后一点也很重要,因为它是关于网络的,对后者的描述也很好。按照惯例,无论线程是否仍在运行,从main
返回都应该退出程序。但是,这取决于语言、编译器和运行库;你在用什么?在任何情况下,您都应该能够通过显式调用ExitProcess
而不是从main
@alk返回来解决此问题。请告诉我是否仍丢失了某些内容netserver enum()
返回哪个值?NERR_Success
(0)@alk谢谢。这确实是我所发布问题的答案,但它并没有真正解决我的问题(这篇文章是我实际问题的一个缩影)。我的实际问题是,我正在与其他一些我没有影响力的功能共享该流程。当我的线程完成时,我希望它在释放所有资源后返回,包括结束所有系统线程。系统线程作为一个整体属于进程,而不是您的特定线程,因此终止它们将是一个非常糟糕的主意。正确退出是父进程作业,你不能和负责它的人谈谈吗?我唯一能想到的另一个选择是让线程启动子进程并在那里执行NetApi工作。好吧,尽管这些系统线程最初只是由线程中的函数创建的,但这是有意义的。不管怎样,我们可以进行物理对话,但由于管理层的决定,我们不能相互影响。调用ExitProcess失败是父进程中的一个错误。即使在没有DLL的情况下它现在不会出现,将来也可能会出现,例如,由于父级使用的一个Win32 API调用的实现更改。也许如果你非正式地提到这个问题会消失。:-)否则,唯一的解决方案是让DLL启动一个子进程,可能是通过rundll32.exe
。
int entry(void)
{
SERVER_INFO_101* si;
DWORD a,b;
NET_API_STATUS c;
c = NetServerEnum ( NULL , 101 , (LPBYTE*) &si , MAX_PREFERRED_LENGTH , &b , &a , SV_TYPE_WORKSTATION, NULL , 0 );
c = NetApiBufferFree (si);
Sleep(1000);
ExitProcess(0);
}