View previous topic :: View next topic |
Author |
Message |
Poita_
Joined: 23 Jul 2010 Posts: 8
|
Posted: Fri Feb 04, 2011 2:58 pm Post subject: Assertion in NSUndoManager when spawning a new thread |
|
|
The following code produces an assertion on Mac OS X. This is tested on OSX 10.6.6 with DMD 2.051 and the latest version of Derelict2 (rev 525).
Code: | import derelict.sdl.sdl;
import derelict.util.compat;
import std.concurrency;
pragma(lib, "derelict/Derelict2/lib/libDerelictSDL.a");
pragma(lib, "derelict/Derelict2/lib/libDerelictUtil.a");
void foo() {}
void main()
{
spawn(&foo);
} |
The error is:
Code: | 2011-02-04 20:45:11.577 test[10214:440b] *** Assertion failure in +[NSUndoManager _endTopLevelGroupings], /SourceCache/Foundation/Foundation-751.42/Misc.subproj/NSUndoManager.m:271
2011-02-04 20:45:11.581 test[10214:440b] +[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.
2011-02-04 20:45:11.584 test[10214:440b] *** Assertion failure in +[NSUndoManager _endTopLevelGroupings], /SourceCache/Foundation/Foundation-751.42/Misc.subproj/NSUndoManager.m:271
2011-02-04 20:45:11.586 test[10214:440b] An uncaught exception was raised
2011-02-04 20:45:11.587 test[10214:440b] +[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.
2011-02-04 20:45:11.588 test[10214:440b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.'
*** Call stack at first throw:
(
0 CoreFoundation 0x98bdb6ba __raiseError + 410
1 libobjc.A.dylib 0x94f93509 objc_exception_throw + 56
2 CoreFoundation 0x98bdb3e8 +[NSException raise:format:arguments:] + 136
3 Foundation 0x90146bb3 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 Foundation 0x90092e11 +[NSUndoManager(NSPrivate) _endTopLevelGroupings] + 160
5 AppKit 0x969a5153 -[NSApplication run] + 577
6 test 0x0000293c D8derelict3sdl7macinit13NSApplication13NSApplication3runMFZv + 56
7 test 0x000061c5 D8derelict3sdl7macinit7SDLMain12_staticCtor3FZv + 7281
8 test 0x0000448b _D8derelict3sdl7macinit7SDLMain9__modctorFZv + 11
9 test 0x00010758 _moduleTlsCtor + 68
10 test 0x00010813 rt_moduleTlsCtor + 11
11 test 0x00014be0 thread_entryPoint + 196
12 libSystem.B.dylib 0x90be885d _pthread_start + 345
13 libSystem.B.dylib 0x90be86e2 thread_start + 34
)
Trace/BPT trap |
I'm trying a few things to get around it, but haven't figured anything out yet. Anyone know how to get around this? |
|
Back to top |
|
|
Poita_
Joined: 23 Jul 2010 Posts: 8
|
Posted: Fri Feb 04, 2011 4:27 pm Post subject: |
|
|
Update:
I've partially solved this problem by making all of Derelict's static constructors shared, and marking all global variables as __gshared.
This solved the immediate issue, but apparently you need an NSAutoReleasePool per thread, so I left that in TLS in the TLS static constructor.
But this caused more problems. Seemingly at random, I would get a bus error when trying to allocate memory in a thread other than the main thread. This didn't happen deterministically.
I've managed to get around this problem by disabling the GC in the new thread, then re-enabling it just as that thread ends. This is good enough for my needs, but I don't think that's a practical long-term solution.
I'll have to do more tests to figure out whether this is an issue with the druntime GC, or if it is to do with the NSAutoReleasePools. It's hard to tell at the moment... |
|
Back to top |
|
|
doob
Joined: 06 Jan 2007 Posts: 367
|
|
Back to top |
|
|
doob
Joined: 06 Jan 2007 Posts: 367
|
|
Back to top |
|
|
Poita_
Joined: 23 Jul 2010 Posts: 8
|
|
Back to top |
|
|
|