我正在使用C ++ / CLI,我创建了2个主题。
loadedThreads = gcnew array<Thread^>(2);
len = 2;
Thread^ th1 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[0] = th1;
Thread^ th2 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[1] = th2;
th1->Start();
th2->Start();
threadsCreated = true;
两个线程都在检查彼此是否还活着:
void Ping()
{
while(true)
{
if(!threadsCreated) { Thread::Sleep(25); continue; }
for(int i = 0; i < len; i++)
{
Thread^ t = loadedThreads[i];
if(!t->IsAlive())
{
_log("some thread is not running");
}
}
Thread::Sleep(25);
}
}
但是如果我使用ProcessHacker终止线程,线程将不再运行但仍然会被标记为活动(IsAlive = true,ThreadState = Running)
这是一个错误吗?它是Process Hacker使用的漏洞吗?
答案 0 :(得分:0)
.NET/CLR threads是托管线程;在应用程序的上下文中管理。托管线程不只是在操作系统中启动一个线程,它们保持线程对象的状态,以便更加开发人员管理线程。
当你启动一个线程时,操作系统必须管理这个线程(无论它来自.NET,Java还是C),而外部程序(如Process Hacker)可以看到这些线程很像外部程序可以看到在系统上运行的进程。 Process Hacker和类似它的可以终止线程的程序通常只是获取操作系统线程ID并调用WinAPI函数TerminateThread
,这实际上会杀死活动线程,而不会有任何其他用户代码在其上执行。
对于托管线程,这意味着当您调用Start
方法时,Thread
类将保持其创建的内部线程的状态(例如线程的ID,将线程状态设置为'running',调用用户函数等)并且当线程函数结束时,Thread
类然后清理并设置适当的标志(例如,线程状态设置为'停止'以进行正常终止或'中止'如果{{3} } 被称为)。对此,如果从外部程序(如Process Hacker)中删除线程,Thread
类代码没有机会预先形成清理代码,从而将标志重置为其有效值,即,Thread
类仍然认为它所拥有的线程是有效的。应该注意的是,在通过Process Hacker杀死它之后对线程对象进行操作很可能会导致崩溃或未定义的行为。
还应该注意的是,没有太多方法可以检测线程是否在代码之外被强行杀死。您可以加入线程或在线程代码中实现一种心跳,但这仍然无法保证(特别是如果您实现任何类型的同步锁)。如果线程被杀死,你可能知道的最多的是线程已经通过某种方式结束,正如你所指出的那样,它可能导致无效状态。
所以,直接回答:
这是一个错误吗?
不,这是上下文所预期的行为。
它是Process Hacker使用的漏洞吗?
不,根据我上面的回答,它很可能使用TerminateThread
函数,但它确实需要管理员权限。
希望可以提供帮助。