【问题标题】:NetServerEnum create Worker Threads who won't closeNetServerEnum 创建不会关闭的工作线程
【发布时间】:2013-06-08 19:15:50
【问题描述】:

在尝试解决我之前提出的SO 问题时,我发现即使没有我的线程,问题也会发生。

我现在拥有的是一个非常简单的单线程代码,它调用 - 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 的线程(使用进程资源管理器),在返回main() 之前,程序会优雅地退出。 我想知道它可能会有用。

UPDATE2:(更多技术信息) 我正在使用: MS Visual Studio 2010 Ultimate x64 (SP1Rel) 在 Win7 Enterprise SP1 代码是 C(但编译为 c++ 开关打开) 子系统:WINDOWS 编译器:cl.exe(使用 IDE) 所有其他参数都是默认的。

我正在使用一个自我修改的入口点 (/ENTRY:"entry"),它是我程序中唯一的函数):

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);

return 0;

}

前面提到的所有测试都是在大约 100 个单元的 Windows 域网络中进行的。

更新 3: 在(非虚拟)WinXP 32 位 上测试时不会出现此问题。 (相同的二进制文件,但对于 Win7 x64 测试了两个二进制文件 - 32bit over WOW 和原生 x64)

【问题讨论】:

  • 你敢发布你的测试程序的完整代码吗?对于那些想要重现您所描述的内容的人来说,这可能会很有趣。此外,有关使用的环境 (OS)、编译器和 SDK 版本的详细信息可能会有所帮助。最后一点也很重要,因为它是关于网络的,对后者的描述也很高兴知道。
  • 按照惯例,无论线程是否仍在运行,从main 返回都应该退出程序。但是,这取决于语言、编译器和运行时库;你在用什么?无论如何,您应该能够通过显式调用ExitProcess 而不是从main 返回来解决问题。
  • @alk 如果还有什么遗漏请告诉我
  • NetServerEnum() 返回哪个值?
  • NERR_Success (0) @alk

标签: windows networking thread-safety threadpool netapi32


【解决方案1】:

当您使用自定义入口点时,您将绕过运行时库,这意味着您有责任退出进程。如果没有更多线程在运行,该进程将隐式退出,但正如您所发现的,操作系统可能会代表您创建您无法控制的线程。

在您的情况下,您需要做的就是在 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 并使用自定义入口点的情况下,您看到的行为符合预期。

【讨论】:

  • 谢谢。它确实是已发布问题的答案,但它并没有真正解决我的问题(这篇文章是对我实际问题的减少)。我的实际问题是我正在与其他一些我没有影响的功能共享该过程。当我的线程完成后,我希望它在释放所有资源后返回,包括结束所有系统线程。
  • 系统线程属于整个进程,而不是您的特定线程,因此终止它们将是一个非常糟糕的主意。正确退出是父进程的工作,你不能和负责它的人说话吗?我能想到的唯一其他选择是让您的线程启动一个子进程并在那里执行 NetApi 工作。
  • 好的,尽管这些系统线程最初是由我线程中的函数创建的,但有些道理。无论如何,我们可以肢体交谈,但由于管理层的决定,我们不能相互影响。
  • 调用 ExitProcess 失败是父进程中的一个错误。即使在没有您的 DLL 的情况下它现在不显示,它也可能在将来出现,例如,由于父级使用的 Win32 API 调用之一的实现更改。也许如果你非正式地提到这个问题就会消失。 :-) 否则,唯一的解决方案是让您的 DLL 启动子进程,可能通过 rundll32.exe
猜你喜欢
  • 2023-03-28
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多