When the first attempt to use a class is made, the +initialize method is
supposed to be called automatically and safely.  The current code check to see
whether +initialize needs to be called by seeing if the dispatch table is
installed.  If the table is not installed, it installs the dispatch table and
calls +initialize using locking to prevent another thread from trying to do the
same thing, but there is a problem ... once the dispatch table for the class
has been installed, it is possible for another thread to use the class before
+initialize completes (ie before the method has had a chance to set up all the
class variables).  This is a rare race condition, but when it occurs it's
extremely hard to recognise and track down.

I think the fix is reasonably straightforward: when this occurs we need to
refrain from installing the dispatch table until +initialize has completed, but
we must make sure that the initializing thread is able to call methods of the
class while it is executing.  The obvious way to do this is to set up a copy of
the dispatch table and have the method lookup use that copy (but only if
locking permits) if there is no installed dispatch table.  Upon completion of
+initialize, the copy is installed as the normal dispatch table so that all
threads can use it.  Unfortunately I haven't had time to implement/test such a
fix yet.


-- 
           Summary: Calling of the +initialize method is not completely
                    thread-safe
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libobjc
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: rfm at gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38307

Reply via email to