TerminateThread中的句柄错误无效

时间:2014-05-27 12:32:54

标签: c++ winapi signals

我有一个应用程序,它通过SetConsoleCtrlHandler注册了句柄例程。事情是休息信号我必须在退出之前做一些清理,那就是问题开始的时候。因为,其他线程继续运行并使用一些应该释放的资源,我在清理期间遇到了访问冲突。我试图保存使用这些资源的线程实例并在调用清理例程之前停止它们,但这没有帮助。我不断得到ERROR_INVALID_HANDLE。我试图通过DuplicateHandle获取线程实例,我也尝试只保存线程ID,然后通过OpenThread函数获取线程句柄。但仍显示无效的句柄错误。

此外,当我枚举所有线程实例并尝试终止它们时,我得到相同的错误。在我看来,在处理例程周围有一些“魔力”,它不允许从它终止其他线程。

枚举所有线程的列表

HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
                    if (h != INVALID_HANDLE_VALUE) {
                        THREADENTRY32 te;
                        te.dwSize = sizeof(te);
                        if (Thread32First(h, &te)) {
                            do {
                                if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
                                    sizeof(te.th32OwnerProcessID)) {
 HANDLE thread = OpenThread(THREAD_TERMINATE, FALSE, te.th32ThreadID);
                                        if (TerminateThread(thread , NUM_SIG_ACTION_1) == 0)
                                        {
  //                                          printf("terminate failed (%d)\n", GetLastError());
                                            if( SuspendThread(thread ) == -1)
                                            {
//                                                printf("suspend failed (%d)\n", GetLastError());
                                            }
                                        }
                                }
                                te.dwSize = sizeof(te);
                            } while (Thread32Next(h, &te));
                        }
                        CloseHandle(h);
                    }

通过DuplicateHandle

列出获取线程
//code in working thread
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_hWorkerThread ,
                             DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS);
//code in handler routine

                if (TerminateThread( g_hWorkerThread , NUM_SIG_ACTION_1 ) == 0)
                {
                    printf("Terminate thread failed (%d)\n", GetLastError());
                }

列出OpenThread

//code from worker thread
g_iWorkerThreadId = GetThreadId(GetCurrentThread());
//code in routine handler
HANDLE handle = OpenThread(THREAD_TERMINATE, FALSE, g_iWorkerThreadId); 
                   if (TerminateThread( handle , NUM_SIG_ACTION_1 ) == 0)
                    {
                        printf("Terminate thread failed (%d)\n", GetLastError());
                    }

无论如何强制处理例程运行到当前工作线程?

任何帮助将不胜感激。

先谢谢。

2 个答案:

答案 0 :(得分:1)

您正在尝试自己做一些操作系统已经做过的事情。不要与系统作斗争。 让我建议另一种工作方式,它可以大大简化您的代码。

当主应用程序线程获得Ctrl信号时,它想要关闭应用程序。 您可以让Windows为您执行此操作,但您可能会将资源置于未定义状态,这就是您希望正常关闭的原因。

可能,每个线程已经运行了一个事件循环 - 这是基本的Windows应用程序范例。在ctrl-signal之后,将事件发布到其他线程并在每个线程的事件循环中捕获它们。添加自定义事件代码,使其优雅地结束自己。您现在只需要等待所有线程句柄以确保所有线程都已结束。

使用TerminateThread并不是一个好主意,它正好与线程的优雅结束相反。

答案 1 :(得分:0)

如何确定调用TerminateThread将释放正在使用的资源?

只有终止进程才能保证释放进程使用的内核资源

在我简陋的经历中,我没有发现任何多线程程序在没有清晰明确的退出机制的情况下运行良好且稳定。

每个线程必须具有退出条件,退出时必须释放资源,主线程(或控制线程)必须触发退出条件并等待所有其他线程退出。