Skip to content
Permalink
Browse files

[runtime] Fix an infinite loop in the runtime class init code. (#4455)

The following can happen:
* Thread T1 starts initialization of C1
* Thread T2 starts initialization of C2
* T2 starts initialization of C1, it gets blocked on T1.
* T1 finishes initializing C1.
* T1 starts initialization of C3.
* T1 starts initialization of C2. It sees that T2 is
  still blocked on T1, but its not actually blocked, since
  C1 is finished. Still, we record that T1 is blocked.
* T3 starts initialization of C2, it gets into an infinite
  loop in the while loop, since the blocked_thread_hash
  now indicates that T1 and T2 are blocked on each other.

The solution is to not mark a thread as blocked, if its waiting
for a thread which is waiting on a finished lock. Fixes hangs
when running csc.
  • Loading branch information
vargaz committed Mar 2, 2017
1 parent cb922c0 commit f0c0314e4d132ffa8114af404a8ea5c21ebe0c87
Showing with 4 additions and 1 deletion.
  1. +4 −1 mono/metadata/object.c
@@ -441,6 +441,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
return TRUE;
}
/* see if the thread doing the initialization is already blocked on this thread */
gboolean is_blocked = TRUE;
blocked = GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (lock->initializing_tid));
while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
if (mono_native_thread_id_equals (pending_lock->initializing_tid, tid)) {
@@ -451,14 +452,16 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
/* the thread doing the initialization is blocked on this thread,
but on a lock that has already been freed. It just hasn't got
time to awake */
is_blocked = FALSE;
break;
}
}
blocked = GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (pending_lock->initializing_tid));
}
++lock->waiting_count;
/* record the fact that we are waiting on the initializing thread */
g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
if (is_blocked)
g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
}
mono_type_initialization_unlock ();

0 comments on commit f0c0314

Please sign in to comment.
You can’t perform that action at this time.