From 2d835cffa666d97e5f4f8724cfa7965c3b06c52e Mon Sep 17 00:00:00 2001 From: theraven Date: Mon, 13 Aug 2012 14:58:58 +0000 Subject: [PATCH] Fix the lock order when sending +initialize, so that we don't hold a lock that is meant to protect a runtime data structure while trying to acquire a lock that must be held when running user code that may take an indeterminate amount of time and may trigger deadlocks. --- dtable.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dtable.c b/dtable.c index a223511..73b8796 100644 --- a/dtable.c +++ b/dtable.c @@ -666,14 +666,11 @@ PRIVATE void objc_send_initialize(id object) objc_send_initialize((id)class->super_class); } - LOCK(&initialize_lock); - // Superclass +initialize might possibly send a message to this class, in // which case this method would be called again. See NSObject and // NSAutoreleasePool +initialize interaction in GNUstep. if (objc_test_class_flag(class, objc_class_flag_initialized)) { - UNLOCK(&initialize_lock); // We know that initialization has started because the flag is set. // Check that it's finished by grabbing the class lock. This will be // released once the class has been fully initialized @@ -684,6 +681,11 @@ PRIVATE void objc_send_initialize(id object) } LOCK_OBJECT_FOR_SCOPE((id)meta); + LOCK(&initialize_lock); + if (objc_test_class_flag(meta, objc_class_flag_initialized)) + { + return; + } // Set the initialized flag on both this class and its metaclass, to make // sure that +initialize is only ever sent once.