dotgnu-general
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [DotGNU]Safely implementing Thread.Abort


From: Russell Stuart
Subject: Re: [DotGNU]Safely implementing Thread.Abort
Date: 20 May 2004 12:18:18 +1000

On Thu, 2004-05-20 at 07:36, Rhys Weatherley wrote:
> Outputting abort check instructions on every backward 
> branch is OK with me, as long as you only do it in 
> programs that use Thread.Abort.  This can be detected 
> by the loader (any assembly with a MemberRef to 
> Thread.Abort is a candidate).

This relies on knowing whether any code calls
Thread.Abort().  There are two issues with that.  First 
of all, how are you going to know?  Scan every assembly 
referenced when you first start up?  Some of these 
assemblies might use Thread.Abort(), and yet it may 
never be called.

Secondly, what about programs that do a 
System.Reflection.Assembly.Load? You might discover 
the loaded assembly might calls Thread.Abort() after 
you have generated some code.  A variation on the theme 
is Remoting.  A remote procedure may call Thread.Abort().  
I see how you could know that.

On Thu, 2004-05-20 at 08:47, Rhys Weatherley wrote: 
> For now, implement the check on backwards jump as-is.

This will always work, but you have generate equivalent 
code for the JIT.  Will you be able to bring yourself 
to do that?  It won't be just an instruction or two.  
The "tst" op-code will overwrite the CPU's condition 
flags, which will have to be restored if you are 
doing a conditional backward jump.  In any decently 
optimised code most of them are conditional.

On Thu, 2004-05-20 at 08:18, Rhys Weatherley wrote:
> How exactly are you going to do that?  The CVM instruction
> pointer is probably going to be in a register (esi on x86).
> You cannot guarantee that the CVM instruction pointer is in
> "thread->pc" when an abort occurs.

This is true.  In fact even in a Unix Signal you will have
no idea of the "true" value of thread->pc - because you don't
in general know what register it is in.

Thus my original suggestion was modify every backward jump
in the current method.

That won't catch every case - the thread being aborted may
be in the middle of constructing/destroying a frame.  The
only way I can see around that is the Abort() method hanging
around until it sees the aborted thread has processed the 
abort, or until its the stack frame changes - in which case 
it has another go at stopping it.

On Thu, 2004-05-20 at 07:36, Rhys Weatherley wrote:
> You cannot use any approach that requires the method code 
> to be modified after it is first generated.  It isn't thread safe: 

I am not convinced of that.  Firstly, no matter what you do,
you have set a thread->aborted flag, and you have to force
the thread to see it, ie you have to force it into the
cache of the CPU it is executing on.  I think all operating
systems that support multiple CPU's provide a means of doing
that, as tum has noted.  Forcing the CPU to see modifications
you have made to its instruction stream is essentially the
same problem.

Secondly, on all multi CPU architectures I know of writes to
a word are atomic.  By this I mean a if a single instruction
writes some bytes that do not cross a word boundary, no CPU
will see some bytes written and some not.  Either they will
see the entire write, or none of it.  Here "word" means
the width of the narrowest memory bus - typically the one
to main memory.  With DIMM's this is 64 bits.

With CVM, where we have control over the op-codes, life is
very simple.  All you need to do is have two versions of the
"backward jump" opcode.  The one normally generated doesn't
check for Abort()'s.  When Abort()'s is executed, you
replace it with one that does. This can't possibly be 
non-thread safe.

With the JIT life gets harder, because you can't typically
just modify one byte.  You have to insert some sort of
"call" instruction.  It could be a "call", or it could
generate a software interrupt (like the ia32 int3).
Whatever you do, providing you can make the modification
with just one write to a word aligned value, you can
get away with it.  This means the JIT would have to word
align the backward jumps and returns.

I don't really think its a question of whether its possible
to implement Thread.Abort() with zero overhead to programs
that don't use it - it is.  With CVM its not even that hard
to do.  With the JIT - well it sounds like an awful lot of 
effort to me, but I can't think of a simpler solution ATM.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]