Detecting kernel initialization

Apparently, Throw is deactivated during kernel initialization. The following function can determine if Throw is inoperative:

throwInoperativeQ[] := CheckAll[Catch[Throw[False]], # /. Null -> True &]

The undocumented function CheckAll is used here because Check also appears to be unreliable when Throw is inoperative.

If we make the assumption that Throw is non-functional if and only if the kernel is still initializing, then we can define:

kernelInitializingQ = throwInoperativeQ;

The deactivation of Throw during initialization seems to be intentional but it might be changed in some future release. This behaviour goes back to at least V7 and probably even earlier. It was reported to WRI and given the classification number [TS 86]. It is the root cause of the defect described in (17164).

I feel that this work-around is on very shaky ground given that it uses an undocumented function, undocumented behaviour, and a lot of guesswork. I offer it up "for science".

Work-around for complex initializations

There are many cases where code that does more than install definitions will fail at start-up. This may very well be due to the deactivation of Throw and similar non-local control flow constructs. If this behaviour is changed is some future release, it may reduce or eliminate the need to detect whether initialization is in progress. In the meantime, using an immediately scheduled task might dodge the problem (depending upon the exact nature of the initialization):

RunScheduledTask[
  (* perform some complex initialization *)
; RemoveScheduledTask @ $ScheduledTask
, {0}
]

After some spelunking, I found a file which contains a lot of initialization code, including reading the kernel init.m file, loading Autoload packages, loading anything set with the -initfile option, starting the paclet manager (which may autoload packages), and many other things. It is

SystemFiles/Kernel/SystemResources/$SystemID/sysinit.m

Towards the end this file sets

System`Private`$InitsLoaded = True;

Thus checking

TrueQ[System`Private`$InitsLoaded]

seems like a practical way to check that initialization has already finished. This symbol is present in at least 9.0–11.0. There are no other references to this symbol in any plaintext .m files in the installation directory (but I don't know about .mx files).


The usual caveats about undocumented stuff apply more than ever.