Hack #30. Reload Modified Modules

Update modules in a running program without restarting.

Developing a long-running program can be a tedious process, especially when starting and stopping it can take several seconds or longer. This is most painful in cases where you just need to make one or two little tweaks to see your results. The Ruby on Rails web programming toolkit in development mode gets it right, automatically noticing when you change a library and reloading it in the running server without you having to do anything.

Perl can do that too.

The Hack

All it takes is a simple module named Module::Reloader:

package Module::Reloader;

use strict;
use warnings;

my %module_times;

INIT
{
    while (my ($module, $path) = each %INC)
    {
        $module_times{ $module } = -M $path;
    }
}

sub reload
{
    while (my ($module, $time) = each %module_times)
    {
        my $mod_time   = -M $INC{$module};
        next if $time = = $mod_time;

        no warnings 'redefine';
        require ( delete $INC{  $module } );
        $module_times{ $module } = $mod_time;
    }
}

1;

At the end of compile time [Hack #70], the module caches the name and modification time of all currently loaded modules. Its reload( ) function checks the current modification time of each module and reloads any that have changed since the last cache check.

Running the Hack

Use the module as usual. Then, when you want to reload any loaded modules, call Module::Reloader::reload( ). In a long-running server process, such as a pure-Perl web server running in development mode for a framework, this is easy to do right before processing a new incoming request.

Provided that the modules being modified don't keep around any weird state between requests, the request will see the new behavior.

Hacking the Hack

The module as written does attempt to avoid spurious warning messages by suppressing Subroutine %s redefined at... error messages, but a compilation error in a module may cause strange behavior and necessitate a server restart. This is for development purposes only; it's very difficult to write code that behaves perfectly in a production environment—too many things could go wrong.

Changing the definition of classes while you have active instances of those classes can do scary things. It may be worthwhile to exclude certain modules, perhaps by specifying filters for modules to include or to exclude.

This module currently does not erase the symbol tables of reloaded modules; that may be useful in certain circumstances. (It may be hazardous in others, where multiple modules affect symbols in a given package.)

Get Perl Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.