In the past, when I've needed this sort of thing, I've structured my code so that there's a well defined state object (which can be pretty complicated), and an "evolver" function that evolves the state object to some final condition. Then I simply use Storable to serialize and save the state object as needed.
This approach may represent a bigger burden on the programmer than what you propose, but I trust it more. After all, this functionality is, almost by definition, useful only with long, i.e. precious, runs. When days' worth of computation are at stake, I prefer to take it upon myself to work out the details of what constistutes a state, and how this state is evolved, etc., rather than letting this analysis be somehow automated after-the-fact. If I were to automate it, I'd go whole-hog and figure out how to save all the memory image to disk and restore it later.
BTW, I find checkpointing useful, but for reasons different from the ones you cite, e.g. suspending a job temporarily to give the CPU to something else. For these I just use kill -STOP/kill -CONT (yes, I'm a Unix creature). Also, GNU screen is invaluable for decoupling processes from login sessions. I often work on remote hosts, through connections that are not infinitely reliable; screen has saved my butt more often than I care to admit. (In fact, for all you Unix users out there, screen is one of those utilities, like Google, that once you start using it, you begin to wonder how anyone could live without it.)