Created attachment 5665 [details]
According to MSDN:
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing.
The key phrase: "When this exception is raised, the runtime executes all the finally blocks before ending the thread."
I wrote simple test to check if it works correctly in mono and could be used for properly locking. When I run it after few minutes application gets in deadlock, the output is varies from time to time. In one time, I can get following output:
Aborted read b1=True, b2=True, b3=True, b4=False, s2=True
Aborted write b1=True, b2=False, b3=False, b4=False, s2=True
What means, that first finally block was not executed, while second was.
Or I can get:
Aborted read b1=True, b2=True, b3=True, b4=False, s2=False
What means, that first finally block was executed, while second was not.
But b1,b2 and s2 must always be 'True' if all finally blocks are executed properly.
Such random looks very strange.
Mono Runtime Engine version 3.2.7 (master/01b7a50 Sat Dec 14 01:48:49 NOVT 2013)
Copyright (C) 2002-2013 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
You can decrease Thread.Sleep() time from 500 to 100 ms, to get the deadlock faster.
And one more thing:
In most cases you won't get a phrase "Gotcha!" on your screen, seems that timeout for TryEnterReadLock does not work correctly.
The testcase is racy, for example, the thread abort request could arrive when the thread is in the second finalizer, but before it executes the b4=true; line.
I'm not sure the last comment is a confirmation of the bug or rejection, so want to mention, if ThreadAbortException is raised in second finally block before b4=true, runtime must execute all statements in the finally block and only after that pass execution flow to catch(ThreadAbortException) block. See remarks for ThreadAbortException class in msdn
And msdn documentation of Thread.Abort method:
The thread is not guaranteed to abort immediately, or at all. This situation can occur if a thread does an unbounded amount of computation in the finally blocks that are called as part of the abort procedure, thereby indefinitely delaying the abort. To wait until a thread has aborted, you can call the Join method on the thread after calling the Abort method, but there is no guarantee that the wait will end.
The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region.
And the code above does not deadlock on MS .NET
This is yet another async bug. When the testcase is aot-ed, it randomly crashes because
the implementation of OP_ATOMIC_ADD_NEW_I4 uses callee-saved regs as temporary regs by push-ing and pop-ing them. If the thread is interrupted in the middle of this code sequence, the unwinder will use
the ebx value set by the code sequence instead of the original pushed value.
not sure if related to this Bug report
at shutdown i get randomly this Stacktrace @mono Master
Failed to close connection: System.Threading.ThreadAbortException
at System.Net.HttpWebRequest.Abort () <0x7f61f82507e0 + 0x00309> in <76b6376638884822b2efb587630d5b7e#2bbc429d4f85cbdaecb5d0cb86d630de>:0
at mytool.WebCrawlerWorker.CloseConnection () <0x7f61f29f2280 + 0x00022> in <630e3cc849c549498c690f2b568f83e5#2bbc429d4f85cbdaecb5d0cb86d630de>:0
at mytool.WebCrawler.Crawl () [0x007cb] in <630e3cc849c549498c690f2b568f83e5>:0
* Assertion at aot-runtime.c:2897, condition `!async' not met
* Assertion at mini-exceptions.c:955, condition `unwind_options == MONO_UNWIND_NONE' not met
any news about this ?