In Perl, there are special blocks (BEGIN, CHECK, INIT, END) that allow you to control when your code is executed:
BEGIN { ... } — executes immediately at compile time (before the main code and before loading modules);CHECK { ... } — executes after all files are compiled, but before their execution (not supported in all versions of Perl);INIT { ... } — executes before the main code starts running ("runtime");END { ... } — executes after the program finishes, when exiting the script.Execution order:
BEGINCHECKINITENDExample:
BEGIN { print "BEGIN executed "; } CHECK { print "CHECK executed "; } INIT { print "INIT executed "; } print "Main code executed "; END { print "END executed "; }
Can a BEGIN block inside a module affect the global state of the program if the module is included using require instead of use?
Answer and example:
BEGIN blocks are executed at compile time, so they will not run if the module is included via require (at runtime, not at compile time), rather than through use (executed at compile time of the including file). This can lead to unexpected behavior if the initialization relies on BEGIN.
Story 1: In one project,
BEGINwas used to initialize environment variables, and the module was included viarequire— as a result, the variables were not set, causing chaos in loading configurations in production.
Story 2: When using the
ENDblock to close a file descriptor, implicit process stops were not taken into account; sometimes theENDblock did not execute due to the Perl interpreter crashing, leading to lost data in logs.
Story 3:
CHECKblocks were the only place for running environment validity tests. The user ran the script in an old version of Perl, where theCHECKblock was not present, and checks simply did not run — critical failures only manifested in production.