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.