Checkpoint-and-restart with DMTCP can create large disk images, and the checkpoint details are controlled by the third-party system. To avoid the problems, the programmers can define their checkpoint-and-restart strategy that better suits the application.
Here is an example of C Program. We would like to add user-defined checkpoint-and-restart code so that the program can periodically save the checkpoint info to a file, and it can restart the execution from the last checkpoint in case an interruption occurs.
#include <iostream>
#include <unistd.h>
 void b (int &);
 void d (int &);
int main() {
   int i1 = 10;
   int i2 = 20;
   d(i1);
   b(i2);
   b(i1);
   printf("Final i1 = %d\n", i1);
   printf("Final i2 = %d\n", i2);
   return 1;
}
void b (int & v) {
   for(int i =0 ; i < 10; i++) {
      v+=i;
      printf("Value changed to %d\n", v );
      sleep(1);
   }
}
void d (int & v) {
   for (int i =0; i < 10; i++) {
      b(v);
   }
}
Here is the sample code with the self-defined checkpoint-and -restart solution:
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
void b (int &);
void d (int &);
int restart_b=0;
int restart_d=0;
static int rose_count_b=0;
static int rose_count_d=0;
int main(int argc, char *argv[]) {
       if(argc > 1 && *argv[1] == 'r'){
         restart_b=1;
         restart_d=1;
         printf("\nThe file will be opened in the restart mode.\n");
       }
       int i1 = 10;
       int i2 = 20;
       rose_count_d =0;
       rose_count_d =0;
       rose_count_d++;  //need to be increased by one every time b() gets called
       d(i1);
       rose_count_b++; //need to be increased by one every time b() gets called
       b(i2);
       rose_count_b++;
       b(i1);
       printf("Final i1 = %d\n", i1);
      printf("Final i2 = %d\n", i2);
       return 1;
}
void b (int & v) {
       int rose_start=0;
       
       static int rose_count_in_file=0;
       static int rose_start_from_file=0;
       static int rose_v_from_file=0;
     
       if(restart_b==1){
          char line[80];
          FILE *fp2;
          fp2 = fopen ("chkpt_b.txt", "r"); 
           if(fgets(line, 80, fp2) != NULL){
              sscanf (line, "%d", &rose_count_in_file);
              
              fgets(line, 80, fp2);
              sscanf (line, "%d", &rose_start_from_file);
              
              fgets(line, 80, fp2);
              sscanf (line, "%d", &rose_v_from_file);
           }  
          fclose(fp2);
          restart_b=0;
       }
   
       printf ("\nrose_count_in_file: %d, rose_count: %d\n",rose_count_in_file, rose_count_b);
       FILE * fp;
       if(rose_count_in_file==rose_count_b){
         rose_start = rose_start_from_file;
         v = rose_v_from_file; 
       }        
         for(int i = rose_start ; i < 10; i++) {
                 
                 if(i==rose_start){
                         printf("\nstarting out from i= %d\n", i);
                 }
                 if(i%5==0){
                         fp = fopen ("chkpt_b.txt", "w");
                         //get the data type of the values to be checkpointed as specified by the user
                         fprintf(fp, "%d\n", rose_count_b);
                         fprintf(fp, "%d\n", i);
                         fprintf(fp, "%d\n", v);
                         fclose(fp);
                 }
                 v+=i;
                 printf("Value changed to %d\n", v );
                 sleep(1);
         }
}
void d (int & v) {
 int rose_start;
 static int rose_count_in_file=0;
 static int rose_start_from_file=0;
 static int rose_v_from_file=0;
 if(restart_d==1){
    char line[80];
    FILE *fp2;
    fp2 = fopen ("chkpt_d.txt", "r"); 
     if(fgets(line, 80, fp2) != NULL){
        sscanf (line, "%d", &rose_count_in_file);
        printf ("\nrose_count_in_file: %d\n",rose_count_in_file);
        fgets(line, 80, fp2);
        sscanf (line, "%d", &rose_start_from_file);
        printf ("\nrose_start_from_file: %d\n",rose_start_from_file );
        fgets(line, 80, fp2);
        sscanf (line, "%d", &rose_v_from_file);
        printf ("\nv_of_d_function: %d\n",rose_v_from_file );
    }
    fclose(fp2);
    restart_d=0;
 }
 FILE* fp;
 if(rose_count_in_file==rose_count_d){
       rose_start = rose_start_from_file;
       v = rose_v_from_file;
 }
              
       
       printf("\nv_D is: %d\n", v);
       for(int i = rose_start ; i < 10; i++) {
               if(i==rose_start){
                       printf("\nstarting out from i= %d\n", i);
               }
               {//Checkpoint must be done before the b() is called. Otherwise, inconsistency occurs 
                       fp = fopen ("chkpt_d.txt", "w");
                       //get the data type of the values to be checkpointed as specified by the user
                       fprintf(fp, "%d\n", rose_count_d);
                       fprintf(fp, "%d\n", i);
                       fprintf(fp, "%d\n", v);
                       fclose(fp);
               }
               
      rose_count_b++;        //needs to be increased by one before the funtion get called, even inside another rountine
               b(v);
               
       }
}
Assuming we name the two files sample.cc and sample_checkpoint.cc, we can compile the sample code as below: 
moudle load gcc/7.3.0
g++ sample.cc -o sample
g++ sample_checkpoint.cc -o sample_checkpoint
To run the sample:
$ ./sample
...........
Value changed to 481
Value changed to 488
Value changed to 496
Value changed to 505
Final i1 = 505
Final i2 = 65
Type in ./sample_checkpoint to run the code with the checkpoint solution. Type in contrl-c to interrupt the execution at some point.
$ ./sample_checkpoint
...........
Value changed to 56
Value changed to 58
Value changed to 61
Value changed to 65
^C
Type in ./sample_checkpoint r to restart the execution from the last checkpoint.
$ ./sample_checkpoint r
..........
Value changed to 56
Value changed to 58
Value changed to 61
Value changed to 65
Value changed to 70
Value changed to 76
----------
Final i1 = 505
Final i2 = 65
-- Zhiwei - 12 Jul 2020