When you run with -X:MTA, is the object now being finalized on a thread other than thread #2?<br><br><div class="gmail_quote">On Thu, Nov 6, 2008 at 7:01 AM, William Reade <span dir="ltr"><<a href="mailto:william@resolversystems.com">william@resolversystems.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Thanks Dino -- it seems that if I use ipy with -X:MTA, I can no longer reproduce the problem. However, this bothers me a bit: I'm not competent to follow all the consequences here, but this situation seems to imply that Ironclad won't be usable safely from any STA thread. Is this an intended restriction or a bug?<br>
<br>
Incidentally, tracking down the call stacks proved to be hard work: the timing changed enough that I only got a single failure over dozens of runs, and it turned out I'd got the logging wrong, so I didn't find out anything useful :(.<div>
<div></div><div class="Wj3C7c"><br>
<br>
Dino Viehland wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I would suggest getting a snap shot of the call stacks when this is happening if that's possible. I can't pin anything down but I wonder if you could have an STA object or something that otherwise requires message pumping. That message pumping could happen while you're doing a Monitor.Enter call. If that was happening maybe there is some subtle CLR bug or a surprise feature? It is surprising that Monitor.Enter can go re-entrant but it can...<br>
<br>
So it'd be interesting to get thread snapshots and see if<br>
<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
EnsureGIL (443) 2<br>
EnsureGIL (443) 1 <- omg, wtf, bbq, etc.<br>
<br>
</blockquote>
<br>
Could be happening because Thread 1 experiences contention, blocks and pumps messages, causing the finalizer thread (2) to run, the lock is acquired and ... ?<br>
<br>
Only other thing I could think of is does it repro on other machines? Maybe it's a hardware bug as unlikely as that seems?<br>
<br>
-----Original Message-----<br>
From: <a href="mailto:users-bounces@lists.ironpython.com" target="_blank">users-bounces@lists.ironpython.com</a> [mailto:<a href="mailto:users-bounces@lists.ironpython.com" target="_blank">users-bounces@lists.ironpython.com</a>] On Behalf Of William Reade<br>
Sent: Wednesday, November 05, 2008 10:01 AM<br>
To: Discussion of IronPython<br>
Subject: Re: [IronPython] Ironclad problem, with which someone here may be able to help<br>
<br>
The log starts in the middle (after many lock/unlocks, some from each<br>
thread); I'm running on x86; and I have no additional AppDomains.<br>
<br>
I don't think it would be safe for me to entirely avoid locking during<br>
finalization, but I could probably cut it down to a quick lock, on a<br>
separate object, to enqueue pointers for cleanup and deallocation on the<br>
main thread. However, I'm reluctant to do that until I'm sure that the<br>
problem is specifically related to GC, otherwise it'll just come back as<br>
soon as anyone tries any serious multithreading :).<br>
<br>
Curt Hagenlocher wrote:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Locking during finalization is often considered to be a bad idea. In<br>
particular, locking without a timeout introduces the possibility that<br>
you will hang the finalization thread, preventing further objects from<br>
being finalized. But clearly, that's not what's happening here.<br>
<br>
Other questions that probably don't matter but might be interesting to<br>
know:<br>
<br>
Can we assume that the finalization thread isn't the first place where<br>
this lock is required? That your log starts somewhere in the middle?<br>
<br>
Is this under x86 or x64 or both?<br>
<br>
Are you creating any additional AppDomains in the process?<br>
<br>
<br>
On Wed, Nov 5, 2008 at 10:15 AM, William Reade<br>
<<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a> <mailto:<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a>>> wrote:<br>
<br>
Hi Curt<br>
<br>
I am indeed; that's how I know thread 2 is the GC thread. Is<br>
locking during GC forbidden?<br>
<br>
William<br>
<br>
Curt Hagenlocher wrote:<br>
<br>
...or, for that matter, any __del__ methods from within Python<br>
-- which ultimately are handled by finalization.<br>
<br>
On Wed, Nov 5, 2008 at 9:37 AM, Curt Hagenlocher<br>
<<a href="mailto:curt@hagenlocher.org" target="_blank">curt@hagenlocher.org</a> <mailto:<a href="mailto:curt@hagenlocher.org" target="_blank">curt@hagenlocher.org</a>><br>
<mailto:<a href="mailto:curt@hagenlocher.org" target="_blank">curt@hagenlocher.org</a> <mailto:<a href="mailto:curt@hagenlocher.org" target="_blank">curt@hagenlocher.org</a>>>><br>
wrote:<br>
<br>
So, the obvious question for me is whether or not you're<br>
using any<br>
finalizers.<br>
<br>
<br>
On Wed, Nov 5, 2008 at 5:57 AM, William Reade<br>
<<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a><br>
<mailto:<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a>><br>
<mailto:<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a><br>
<mailto:<a href="mailto:william@resolversystems.com" target="_blank">william@resolversystems.com</a>>>><br>
<br>
wrote:<br>
<br>
Hi all<br>
<br>
While running the numpy tests, I've come across a situation<br>
which, to the best of my knowledge, is simply<br>
impossible. I'm<br>
hoping that one of the local .NET gurus will be able to<br>
tell<br>
me what I'm missing, or point me somewhere I can get<br>
more insight.<br>
<br>
The 4 methods involved are as follows:<br>
-----------------------<br>
public int GetThreadId()<br>
{<br>
return Thread.CurrentThread.ManagedThreadId;<br>
}<br>
<br>
public void WriteFlush(string info)<br>
{<br>
Console.WriteLine(info);<br>
Console.Out.Flush();<br>
}<br>
<br>
public void EnsureGIL()<br>
{<br>
Monitor.Enter(this.dispatcherLock);<br>
this.WriteFlush(String.Format(<br>
"EnsureGIL ({1}) {0}", this.GetThreadId(),<br>
Builtin.id(this.dispatcherLock)));<br>
}<br>
<br>
public void ReleaseGIL()<br>
{<br>
this.WriteFlush(String.Format(<br>
"ReleaseGIL ({1}) {0}\n", this.GetThreadId(),<br>
Builtin.id(this.dispatcherLock)));<br>
Monitor.Exit(this.dispatcherLock);<br>
}<br>
-----------------------<br>
...and they can, and do, occasionally produce output as<br>
follows:<br>
-----------------------<br>
EnsureGIL (443) 2<br>
EnsureGIL (443) 1 <- omg, wtf, bbq, etc.<br>
ReleaseGIL (443) 2<br>
<br>
EnsureGIL (443) 2<br>
ReleaseGIL (443) 1<br>
<br>
ReleaseGIL (443) 2<br>
-----------------------<br>
When this happens, the process continues happily for a<br>
short<br>
time and then falls over in a later call to ReleaseGIL<br>
(after<br>
successfully calling it several times). The error is "<br>
Object<br>
synchronization method was called from an<br>
unsynchronized block<br>
of code", which I understand to mean "you can't release<br>
this<br>
lock because you don't hold it".<br>
<br>
It doesn't happen very often, but I can usually<br>
reproduce it<br>
by running<br>
test_multiarray.TestFromToFile.test_malformed a few<br>
hundred times. It may be relevant to note that thread 2<br>
is the<br>
GC thread, and thread 1 is the main thread. I have<br>
considered<br>
the following possibilities:<br>
<br>
(1) That I'm locking on the wrong object. I believe<br>
that isn't<br>
the case, because it's constructed only once, as a "new<br>
Object()" (ie, a reference type), and is only subsequently<br>
used for locking; and, because it keeps the same ipy id<br>
throughout.<br>
<br>
(2) That Monitor.Enter occasionally allows two different<br>
threads to acquire the same lock. I consider this extremely<br>
unlikely, because... well, how many multithreaded .NET apps<br>
already exist? If Monitor really were broken, I think we'd<br>
probably know about it by now.<br>
<br>
(3) That calling Flush() on a SyncTextWriter (the type of<br>
Console.Out) doesn't actually do anything, and the<br>
output is<br>
somehow wrongly ordered (although I can't imagine how this<br>
could actually be: if the locking is really working,<br>
then my<br>
console writes are strictly sequential). I don't have<br>
access<br>
to the code, so I have no idea how it's implemented,<br>
but even<br>
if this is the case it doesn't help much with the<br>
fundamental<br>
problem (the synchronisation error which follows).<br>
<br>
Apart from the above, I'm out of ideas. Can anyone suggest<br>
what I've missed?<br>
<br>
William<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<mailto:<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a>><br>
<mailto:<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<mailto:<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a>>><br>
<br>
<br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
<br>
<br>
------------------------------------------------------------------------<br>
<br>
<br>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a> <mailto:<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a>><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
<br>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a> <mailto:<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a>><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
<br>
------------------------------------------------------------------------<br>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
<br>
</blockquote>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
<br>
<br>
</blockquote>
<br>
_______________________________________________<br>
Users mailing list<br>
<a href="mailto:Users@lists.ironpython.com" target="_blank">Users@lists.ironpython.com</a><br>
<a href="http://lists.ironpython.com/listinfo.cgi/users-ironpython.com" target="_blank">http://lists.ironpython.com/listinfo.cgi/users-ironpython.com</a><br>
</div></div></blockquote></div><br>