C# Threading, and suspending or killing a thread

G

Guest

Hello,

I've got an issue where a process in a third party application has a dll
which while exiting sort of freezes and runs away with processor cycles.

i've written a block of code so that I can drill down into the process, and
get the offending Thread's ID (since the only ones that will have the issue
have higher User processor Time).

But, I can't figure out how to have my .Net app 'kill' or 'suspend' a Thread
based on the Id I have gotten. I see a lot of samples on how to do this with
treads your application starts itself, but nothing 'external' to the app.

Anyone able to lend a hand?

Here's my base routine.....


private static void DoSuspendThread(string processName)
{
// Suspend thread
Console.WriteLine("Passed " + processName);

try
{

Process[] myProcesses = Process.GetProcessesByName(processName);

foreach (Process myProcess in myProcesses)
{

foreach (ProcessThread t in myProcess.Threads)
{
// info += myProcess.ProcessName + " " + t.Id + " " +
t.UserProcessorTime + Environment.NewLine;
TimeSpan time = new TimeSpan(0, 1, 0, 0, 0);
if ((t.UserProcessorTime > time) && (t.ThreadState ==
System.Threading.ThreadState.Running))
{

// Kill or suspend here


}
}


}


}
catch (Exception e)
{
Console.WriteLine("Exception " + e.Message);
}
}
 
M

Markus Stoeger

Rob said:
Hello,

I've got an issue where a process in a third party application has a dll
which while exiting sort of freezes and runs away with processor cycles.

i've written a block of code so that I can drill down into the process, and
get the offending Thread's ID (since the only ones that will have the issue
have higher User processor Time).

But, I can't figure out how to have my .Net app 'kill' or 'suspend' a Thread
based on the Id I have gotten. I see a lot of samples on how to do this with
treads your application starts itself, but nothing 'external' to the app.

Anyone able to lend a hand?

I'd definitely get them to fix their code instead of creating ugly
workarounds. No piece of code lasts longer than a workaround.

Max
 
Y

Yuan Ren[MSFT]

Hi,

Thanks for your post!

From your description, my understanding is that you want to kill some
threads from another .NET application. If I have misunderstood anything,
please let me know.

As far as I know, if you want to kill the thread, you have to use the Win32
API to approach this. I'll explain this limitation later. First of all, I
don't recommend you kill the thread in the foreach statement. I suggest you
save the thread id which you want to kill in some structures such as array
or array list. Then, you can call OpenThread method to get the handle of
the thread. After performing, please call TerminateThread function to kill
the thread directly. You can obtain more information about these two
methods by accessing link below:
OpenThread:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas
e/openthread.asp

TerminateThread:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas
e/terminatethread.asp

BTW, you should use these methods by P/Invoke. If you have anything
unclearly about the P/Invoke, please feel free to let me know.

Actually, this way is not recommend because the ProcessThread is supposed
only to get some information but not performing manipulations. That's way
there is no abort, suspend, join method in the ProcessThread unlike the
Thread class. So, the better way is get the fix or workaround from the
software vendor as Max mentioned. Thanks for your understanding!

Regards,

Yuan Ren [MSFT]
Microsoft Online Support
======================================================
PLEASE NOTE the newsgroup SECURE CODE and PASSWORD were
updated on February 14, 2006. Please complete a re-registration process
by entering the secure code mmpng06 when prompted. Once you have
entered the secure code mmpng06, you will be able to update your profile
and access the partner newsgroups.
======================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from this issue.
======================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
======================================================
 
G

Guest

I'm not sure if it makes a difference, but its not a thread from another .NET
application.

I know ideally it would be best for the vendor to just 'fix' the problem,
but, they are having a hard time admitting to the problem, and discovering
the cause (and their first answer is 'upgrade' which could prove even more
problematic than killing threads that are looking like they've done their
task and are exiting).

P/Invoke does look like the road to go... just a long dark and scary road.

Thanks for the assist,

Rob
 
W

Willy Denoyette [MVP]

Honestly, I don't think this is the road to go, take a look at the
description of TerminateThread, especially the remarks, if these aren't
enough reason NOT to kill arbitrary threads in a another process, well, go
ahead, I wish you all the luck.
Anyway, you need to find out what's really hapening, I'm not entirely clear
on what you mean with "... has a dll which while exiting ...", what exactly
do you mean with that? Another thing which I'm not sure about is who creates
the thread, the DLL code or the client code? And is the client code also a
third party?



Willy.



| I'm not sure if it makes a difference, but its not a thread from another
..NET
| application.
|
| I know ideally it would be best for the vendor to just 'fix' the problem,
| but, they are having a hard time admitting to the problem, and discovering
| the cause (and their first answer is 'upgrade' which could prove even more
| problematic than killing threads that are looking like they've done their
| task and are exiting).
|
| P/Invoke does look like the road to go... just a long dark and scary
road.
|
| Thanks for the assist,
|
| Rob
|
 
G

Guest

The thread itself is created by a service process (a web server's ISAPI that
handles authentication). It makes some calls to a dll (msvcrt.dll) and the
info from ProcessExplorer shows it as msvcrt.dll!endthreadex+0x2f.

Other threads that are spawned like this go right back to zero CPU, and just
go away. But sometimes they get stuck (with 25-50% of the CPU) and just hang
around. I've use the Process Explorer tool to suspend and to kill the
threads, and its had no detrimental effect on the service. The web service
call that generated the issue completes successfully, and subsequent calls
all work fine. That's what I meant by 'while it was exiting'.

The reason we're looking at this is that these hanging threads can eat up
100% CPU with just 2 or 4 of these calls hung. Not a perfect reason to
terminate the thread, but, while we're waiting on the vendor, it beats us
having to term serv into the web server and run the Process Explorer to kill
it there.
 
?

=?iso-8859-1?Q?Lasse=20V=e5gs=e6ther=20Karlsen?=

The thread itself is created by a service process (a web server's
ISAPI that handles authentication). It makes some calls to a dll
(msvcrt.dll) and the info from ProcessExplorer shows it as
msvcrt.dll!endthreadex+0x2f.

Other threads that are spawned like this go right back to zero CPU,
and just go away. But sometimes they get stuck (with 25-50% of the
CPU) and just hang around. I've use the Process Explorer tool to
suspend and to kill the threads, and its had no detrimental effect on
the service. The web service call that generated the issue completes
successfully, and subsequent calls all work fine. That's what I meant
by 'while it was exiting'.

The reason we're looking at this is that these hanging threads can eat
up 100% CPU with just 2 or 4 of these calls hung. Not a perfect
reason to terminate the thread, but, while we're waiting on the
vendor, it beats us having to term serv into the web server and run
the Process Explorer to kill it there.

When you terminate a thread in a .NET application you should consider the
whole appdomain doomed, as in, you should no longer keep it around.

While you said it was not a thread in another .NET application, the comment
is no less appropriate.

If you terminate a thread from the outside (of the thread, could be in the
same process), then you risk the following:

- memory leak, the thread did not get to its cleanup code
- resource leak (open files, sockets, etc.), the thread did not get to is
cleanup code
- invalid application state, the thread did not finalize its changes to internal
variables and might leave the application in a state that is invalid
- deadlocks, if the thread locks internal resources it will never unlock
them, thus blocking future threads from ever accessing the resources the
lock protects

Considering this is a service I'd avoid this at all cost. If you absolutely
have to kill the thread, can you restart the service in question so that
its state is again valid?
 
W

Willy Denoyette [MVP]

| The thread itself is created by a service process (a web server's ISAPI
that
| handles authentication). It makes some calls to a dll (msvcrt.dll) and
the
| info from ProcessExplorer shows it as msvcrt.dll!endthreadex+0x2f.
|
| Other threads that are spawned like this go right back to zero CPU, and
just
| go away. But sometimes they get stuck (with 25-50% of the CPU) and just
hang
| around. I've use the Process Explorer tool to suspend and to kill the
| threads, and its had no detrimental effect on the service. The web
service
| call that generated the issue completes successfully, and subsequent calls
| all work fine. That's what I meant by 'while it was exiting'.
|
| The reason we're looking at this is that these hanging threads can eat up
| 100% CPU with just 2 or 4 of these calls hung. Not a perfect reason to
| terminate the thread, but, while we're waiting on the vendor, it beats us
| having to term serv into the web server and run the Process Explorer to
kill
| it there.

I assume that both ISAPI and the DLL are implemented using pure native C++,
please correct me if I'm wrong, this is extremely important.
Ok assumed all is unmanaged, so you have a ISAPI DLL that runs a thread
procedure (from the third party DLL) and this thread procedure gets stuck
when it returns (that is when it calls _endthreadex as a result of the
return or explicitly). That means that your webrequest hangs (does not
progress) until you kill that thread, right?
Now what happens in _endthreadex is not something that would cause an
endless loop, so I doubt the explorer info is accurate, my guess is that
_endthreadex is actually running ThreadExit(..) which calls the attached
DLL's (all of them) DllMain function to indicate that the thread is
detaching from the DLL. So, I think your thread is looping in a (the third
party?) DLL's detach function, or you are kind of deadlocking on a detach
(DllMain can only be entered by one thread at a time!). The only thing you
can do to be sure of this is to attach a debugger (instead of explorer),
find out which thread is 'stuck and where (which DLL). Another thing you can
do is ask your vendor what he is doing in the DllMain detach function.
Again, it's very bad practice to kill such a thread, don't forget that you a
running inside IIS and that when killing a thread you will leak a thread
handle, the TLS and the stack assigned to the thread, so after some time
your IIS server will die taking all applications running inside the worker
processes with him, not a pretty picture.

Willy.
 
Y

Yuan Ren[MSFT]

Hi,

Thanks for your reply!
"I'm not sure if it makes a difference, but its not a thread from another
..NET application."
No matter want kinds of the application, I think using the way which I
mentioned before is an only way to do this, if you can not obtain any fix
for the current issue.

Regards,

Yuan Ren [MSFT]
Microsoft Online Support
======================================================
PLEASE NOTE the newsgroup SECURE CODE and PASSWORD were
updated on February 14, 2006. Please complete a re-registration process
by entering the secure code mmpng06 when prompted. Once you have
entered the secure code mmpng06, you will be able to update your profile
and access the partner newsgroups.
======================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from this issue.
======================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
======================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top