[Top][All Lists]

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

Re: Deadlock in NSLog

From: David Chisnall
Subject: Re: Deadlock in NSLog
Date: Mon, 4 Aug 2008 14:00:30 +0100

On 4 Aug 2008, at 13:29, David Ayers wrote:

Am Montag, den 04.08.2008, 12:56 +0100 schrieb David Chisnall:

I don't care whether libobjc uses its own threading implementation or
not, however there is no reason for GNUstep to be using an
inefficient and potentially (in this case, definitely) buggy wrapper
around pthreads, rather than using pthreads directly.  The threading
abstraction in libobjc implements the minimal functionality required
for libobjc, not the minimal functionality required in general, or
required for GNUstep.

That assumes that ObjC code using GNUstep also does not use the libobjc
API directly for certain features that OpenStep/Cocoa did/does not
export. I don't believe that is a safe assumption. In fact I would be
very surprised if code that uses threading in meaingfull ways does not
rely on some of those features.

I've come across a lot of code in Objective-C applications that uses POSIX thread calls directly (this is even what Apple's Cocoa docs recommend if NSThread and friends are not adequate for your purposes), but none that calls GNU runtime threading functions other than GNUstep. Note that these are GNU runtime specific - the NeXT, Apple, and Étoilé runtimes all use POSIX threads directly. I am not sure what happens with NSLock if you try to compile it with the NeXT/ Apple runtime. Possibly it just doesn't work. It will need rewriting before it can support the Étoilé runtime (and, thus, much of Objective-C 2) anyway.

NSRecursiveLock is implemented on top of objc_mutex, which emulates a
recursive mutex on top of a non-recursive pthread (or other platform-
specific) mutex.

If this wrapper is broken, then please file a bug (or even fix it since
this seems to be the pthread implementation which you are refering

The wrapper works in the specific usage patterns for libobjc. It is not a general wrapper.

Quite how this makes more sense than using a
recursive pthread mutex is beyond me.

Because libobjc wraps the threading API for a reason. I don't claim to know all the reasons. I'm weary of ignoring them since debugging those issues is painful. So if libpthread (note I'm not stating POSIX... but
a specific implementation that -base would link to).

It wraps threading APIs because it is old, and when it was written there was a Solaris threading API, an HPUX threading API, and IRIX threading API, but no standard threading API.

It continues to wrap it because it, like GCC, supports non-POSIX platforms such as Windows, OS/2, and VxWorks where POSIX is not a native API.

On platforms without native
pthreads support, there are pthread-compatibility libraries that are
a lot better tested for general-purpose use than the libobjc code.

I cannot asses that evaluation, but I do clearly see a benifit in fixing
libobjc rather than working around this in -base.  If those
pthread-compatibility libraries are so much better, then libobjc should be using them. I have no issue with that. In fact I think it would be
great if libobjc could be simplified in this fasion.

For libobjc to use them would introduce a dependency on POSIX into libobjc. You can use libobjc and GCC to compile Objective-C code that does not use GNUstep and that uses the platform APIs directly. Adding a dependency on POSIX would be counter to the goals of GNU libobjc.

libobjc has to support more platforms than GNUstep.  For example, it
supports VxWorks and Windows directly.  In order to use GNUstep on
these platforms, you need a POSIX API layer, such as cygwin or mingw,
which implements its own pthread wrapper.  If you do this, then some
code will be using the cygwin / mingw / whatever wrapper code around
the native APIs, and some will be using the libobjc wrapper around
the native APIs.

Since GNUstep depends on POSIX for a lot of -base, I see no reason
why it can't use POSIX functions.

Well, there is a lot of code in -base that you would have adapt to
remove the dependency of libobjc's threading implementation.  In fact
I'm not even sure if the NSWillBecomeMutlithread hook can reliably be
called via the libobjc runtime if -base was configured with a different
threading library than libobjc.  (Of course it would happen to work if
the threading libraries happend to be identical).

NSWillBecomeMultithreaded should not be depended upon in any case. Recent versions of Cocoa always run in multithreaded mode due to difficulties in safely handling the notification and of interoperating with code that uses pthreads directly (which Apple have been encouraging for a while, although less so with the NSThread extensions in 10.5).

On OS X, NSWillBecomeMultithreaded is delivered if, and only if, new threads are created with NSThread. It is the responsibility of NSThread to send this notification, and has nothing at all to do with whether the thread APIs are called via a wrapper or not (I believe early versions of OS X used Mach locks rather than POSIX ones (which were slightly slower) but this doesn't matter unless you expect to be able to lock a mutex with pthread_mutex_lock and unlock it with - [NSLock unlock], which neither Cocoa nor GNUstep support).

But maybe you can explain why you do not seem to see an merit in fixing
the libobjc wrapper.

Because it is not broken as used by libobjc. It was never intended as a general-purpose threading abstraction layer, just as one that allowed the specific use cases required by libobjc. Fixing it in the general case would require a lot of work which has already been done operating system / libc maintainers.


reply via email to

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