/// <summary> /// Will at least try to process all queued system messages: in case of /// failure simply drop and go on to the next, because there is nothing to /// restart here (failure is in <see cref="ActorCell"/> somewhere …). In case the mailbox /// becomes closed (because of processing a <see cref="Terminate"/> message), dump all /// already dequeued message to deadLetters. /// </summary> private void ProcessAllSystemMessages() { Exception interruption = null; var messageList = SystemDrain(SystemMessageList.LNil); while (messageList.NonEmpty && !IsClosed()) { var msg = messageList.Head; messageList = messageList.Tail; msg.Unlink(); DebugPrint("{0} processing system message {1} with {2}", Actor.Self, msg, string.Join(",", Actor.GetChildren())); // we know here that SystemInvoke ensures that only "fatal" exceptions get rethrown #if UNSAFE_THREADING try { Actor.SystemInvoke(msg); } catch (ThreadInterruptedException ex) // thrown only if thread is explicitly interrupted, which should never happen { interruption = ex; } catch (ThreadAbortException ex) // can be thrown if dispatchers shutdown / application terminates / etc { interruption = ex; } #else Actor.SystemInvoke(msg); #endif // don't ever execute normal message when system message present! if (messageList.IsEmpty && !IsClosed()) { messageList = SystemDrain(SystemMessageList.LNil); } } /* * if we closed the mailbox, we must dump the remaining system messages * to deadLetters (this is essential for DeathWatch) */ var dlm = Actor.Dispatcher.Mailboxes.DeadLetterMailbox; while (messageList.NonEmpty) { var msg = messageList.Head; messageList = messageList.Tail; msg.Unlink(); try { dlm.SystemEnqueue(Actor.Self, msg); } #if UNSAFE_THREADING catch (ThreadInterruptedException ex) // thrown only if thread is explicitly interrupted, which should never happen { interruption = ex; } catch (ThreadAbortException ex) // can be thrown if dispatchers shutdown / application terminates / etc { interruption = ex; } #endif catch (Exception ex) { Actor.System.EventStream.Publish(new Error(ex, GetType().FullName, GetType(), $"error while enqueuing {msg} to deadletters: {ex.Message}")); } } // if we got an interruption while handling system messages, rethrow it if (interruption != null) { // no need to clear interrupted flag in CLR, unlike JVM throw interruption; } }