bugGNUstep - Bugs: bug #24784, Thread safety issue with...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #24784: Thread safety issue with NSCalendarDate...

Submitted by:  Gregory John Casamento <gcasa>
Submitted on:  Sat 08 Nov 2008 10:45:27 PM UTC  
 
Category: Base/FoundationSeverity: 3 - Normal
Item Group: BugStatus: Fixed
Privacy: PublicAssigned to: None
Open/Closed: Closed

(Jump to the original submission Jump to the original submission)

Thu 19 Jan 2012 10:23:08 AM UTC, comment #11:

More recent versions of the GNU runtime have fixed this.

Richard Frith-Macdonald <CaS>
Project Member
Fri 05 Feb 2010 06:16:22 PM UTC, comment #10:

Well, as this is not a GNUstep bug, and I've provided a fix to the gcc maintainers, I'll mark it as fixed. In practice though, people should consider either building a patched libobjc from source or experimenting with libobjc2 from the gnustep svn repository.

Richard Frith-Macdonald <CaS>
Project Member
Fri 09 Jan 2009 08:33:43 AM UTC, comment #9:

Yes it is complicated :-(

And yes, the main problems are because I had to maintain performance in the normal case and maintain binary backwards compatibility.

Unfortunately the idea of the meta-class use does not seem workable (unless I misunderstand). The dispatch table of the class contains its instance methods and the dispatch table of the meta-class contains the class methods.

During execution of +initialize we therefore want both dtables to be available to the current thread, so that +initialize can call both class and (eg if a single shared instance is created at that point) instance methods. At the same time we want neither dispatch table to be visible to other threads (so the other threads can't execute eiter class methods or instance methods).

Richard Frith-Macdonald <CaS>
Project Member
Mon 05 Jan 2009 09:54:43 AM UTC, comment #8:

Thanks!

I've looked at the patch and it looks correct but does seem rather complicated but I believe I understand the dilemma.

We want to avoid adding extra checks (like CLS_ISINITIALIZED which would have to be adapted anyways) the hot path.

We are constrained in the class structure layout due to binary compatibility (or we would add a preliminary dtable there to avoid the external linked list, and have message dispatch also check there under the recursive lock on the cold path).

But I'm wondering if we could use the dtable of the meta class during initialization as a fallback for the cold path under the mutex... i.e.:

if
a) the classes dtable is not set yet
b) the dtable of the meta class is set

assume we are currently initializing so lets take the mutex to insure we are thread that's initializing (double checking once we have the lock to see if some other thread was just finishing up)

If we got the lock and the dtable of the meta class is still set, we can assume this is the thread sending a message lookup during +initialize. We use the meta classes dtable for message lookup to finish processing +initialize.

I still need to verify that the dtable of the meta class isn't used for anything else. I'm also haven't convinced myself that this can't produce a deadlock yet. But it would be great if we could avoid the linked list and all the extra helper functions.

I was hoping to come up with a proof-of-concept during the holidays but that didn't work out so I decided to post the idea for now.

David Ayers <ayers>
Project Member
Thu 01 Jan 2009 03:04:26 PM UTC, comment #7:

I added a patch for a bugfix for this to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38307
I'd appreciate it if other people could have a look at it and spot any errors, though it seems to be working for me.

Richard Frith-Macdonald <CaS>
Project Member
Mon 08 Dec 2008 01:16:44 PM UTC, comment #6:

I think that would be an excellent idea. Thanks for looking into this further. :)

Gregory John Casamento <gcasa>
Project Administrator
Mon 08 Dec 2008 08:48:06 AM UTC, comment #5:

I added a gcc/libobjc bug report for this at
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38307

I can supply a patch against gcc subversion for the runtime if people are interested.

Richard Frith-Macdonald <CaS>
Project Member
Mon 10 Nov 2008 07:07:52 AM UTC, comment #4:

The exception reports the class as being an NSCalendarDate instance, not an NSDate instance, so it's not that the message is going to the wrong class, but the class has no implementation of the method ... however the class does implement the method, so it must be a problem with the dispatch table causing the method lookup to fail, which certainly sounds like an objc runtime error.

My guess is that it's like bug #20163 which is due to the runtime allowing one thread to execute methods of a class while another thread is still calling +initialize

I thought I'd reported that one on the gcc bug tracker, but I can't find it.

Richard Frith-Macdonald <CaS>
Project Member
Mon 10 Nov 2008 05:44:21 AM UTC, comment #3:

For some reason when it reaches the following code in NSLog.m:

else
{
prefix = [NSString
stringWithFormat: @"%@ %@[%d] ",
---->> [[NSCalendarDate calendarDate]
descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S.%F"],
[[NSProcessInfo processInfo] processName],
pid];
}
}

The line indicated calls the method to instatiate a calendarDate object, but for some reason in that method it appears that an NSDate is being used. I'm not sure why.

Here's the method that's being called:

+ (id) calendarDate
{
id d = [[self alloc] init];

return AUTORELEASE(d);
}

For some reason, self here is NSDate and NOT NSCalendarDate as one would expect (given that it was invoked with NSCalendarDate as the class).

Is it possible that this is a thread safety issue in the runtime?

GC

Gregory John Casamento <gcasa>
Project Administrator
Mon 10 Nov 2008 04:48:42 AM UTC, comment #2:

Please see the following:

/home/heron/Development/gnustep/core/base/Testing/synctest/obj/SyncTest: Uncaught exception NSGenericException, reason: subclass NSCalendarDate(instance) should override initWithTimeIntervalSinceReferenceDate:
2008-11-09 23:50:00.149 SyncTest[31952] Before the sync block <NSThread: 0x558980>

This is happening with the attached program. It happens occasionally. This means there is a race condition between these two threads that is causing this to happen.

(file #16812)

Gregory John Casamento <gcasa>
Project Administrator
Sat 08 Nov 2008 10:49:58 PM UTC, comment #1:

What is the bug? What method(s) are concerned and in what way are they unsafe?

Richard Frith-Macdonald <CaS>
Project Member
Sat 08 Nov 2008 10:45:27 PM UTC, original submission:

When NSCalendarDate is entered by two threads this is causing an exception to occur. I was seeing this periodically when NSLog was trying to output information from both threads in the SyncTest tool I wrote to test @synchronize.

Gregory John Casamento <gcasa>
Project Administrator

 

Attached Files
file #16812:  main.m added by gcasa (938B - application/octet-stream - @synchronize test program with NSLogs to illustrate the exception.)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -unavailable- added by ayers (Posted a comment)
  • -unavailable- added by CaS (Posted a comment)
  • -unavailable- added by gcasa (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

    Please enter the title of George Orwell's famous dystopian book (it's a date):

     

     

    Follow 5 latest changes.

    Date Changed By Updated Field Previous Value => Replaced By
    Thu 19 Jan 2012 10:23:08 AM UTCCaSOpen/ClosedAnalyzed=>Closed
    Fri 05 Feb 2010 06:16:22 PM UTCCaSStatusNeed Info=>Fixed
      Open/ClosedOpen=>Analyzed
    Mon 10 Nov 2008 04:48:42 AM UTCgcasaAttached File-=>Added main.m, #16812
    Sat 08 Nov 2008 10:49:58 PM UTCCaSStatusNone=>Need Info

    Back to the top


    Powered by Savane 3.1-cleanup1