15
$\begingroup$

Certain operations do not work during kernel initialization. Code from Kernel/init.m, the Autoload directory, or packages set to autoload may evaluate at initialization time.

Is there a way to detect if the kernel is currently initializing?

I need a piece of code that returns True if it is evaluated during initialization, e.g. if it is placed in init.m.


Clarification: I am not looking to see if the currently loading file is init.m. Any init.m may load at another time than initialization and even at init time, other files may get loaded too, or other code may get evaluated.

$\endgroup$
  • $\begingroup$ As far as init.m files go, you could use something like StringMatchQ[$InputFileName, __ ~~ "init.m"]. You could make it more precise by explicitly listing locations where init.m matters (i.e. system ones, to differentiate from packages). $\endgroup$ – Leonid Shifrin Nov 27 '16 at 16:14
  • $\begingroup$ Would StringContainsQ[NotebookFileName[EvaluationNotebook[]], "init.m"] work? $\endgroup$ – Sjoerd C. de Vries Nov 27 '16 at 16:20
  • 5
    $\begingroup$ I'm not sure if this should be a serious suggestion or not... but until the long-standing bug reported in (17164) is fixed, we can detect initialization using initializingQ[] := CheckAll[Catch[Throw[False]], # /. Null -> True &]. $\endgroup$ – WReach Nov 27 '16 at 16:58
  • $\begingroup$ @Leonid I wanted to use it for the following: My package uses Import and RunProcess during loading. These don't work during initialization. After I added proper documentation, there's a setting in the doc center to make the package load on startup. If a user sets it, it will mess everything up. So I want to make the package "initialization-resistant" by delaying "dangerous" operations until a package function is used for the first time. But in general it is more user-friendly to let the package report misconfiguration as soon as it ... $\endgroup$ – Szabolcs Nov 27 '16 at 19:20
  • $\begingroup$ @Leonid ... is loaded. So I only want to delay these operations if the package is set to load at startup, but not otherwise. I know that this sounds like a whole lot of complication for little gain, but I thought it doesn't hurt to ask. Now I found a way to detect initialization, but I am not really comfortable using such stuff. So I might just not implement this at all. Still investigating initializing[] from WReach. $\endgroup$ – Szabolcs Nov 27 '16 at 19:22
14
$\begingroup$

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}
]
$\endgroup$
  • $\begingroup$ So scheduled tasks are delayed until initialization has finished? Let me try this. $\endgroup$ – Szabolcs Nov 27 '16 at 21:11
  • 5
    $\begingroup$ Yes. I have used this work-around successfully before. However, take note that the asynchronous nature of those tasks might permit some processing to sneak in before the task fires, introducing the possibility of a race condition. Like so much in WL, a work-around that is just fine for an end user might not be suitable for use in a library. Library writers have a tough time in WL :( $\endgroup$ – WReach Nov 27 '16 at 21:13
  • $\begingroup$ @WReach Everybody has a tough time in WL ... $\endgroup$ – Rolf Mertig Nov 27 '16 at 22:55
  • $\begingroup$ According to Ilian, 1 sec should be enough :) Possible Bug of loading Package $\endgroup$ – Kuba Nov 28 '16 at 6:12
  • 1
    $\begingroup$ @Kuba Errrm, not really... all that post claims is that an example (exempli gratia) time of 1 second is something I've used as a workaround. Your mileage may vary. $\endgroup$ – ilian Nov 28 '16 at 20:36
14
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.