GLPK/Error handling

This page describes strategies for dealing with faults states in GLPK — while noting that prevention is usually better than cure.


GLPK error hook function edit

If a run-time error occurs in the GLPK library, GLPK, by default, normally releases the GLPK library environment and aborts the calling program. If you would like to prevent the calling program being aborted, then define a custom error hook function and register this function by calling glp_error_hook. Your hook function should first invoke glp_free_env to free the GLPK library environment and then apply the longjmp call from the C standard library header setjmp.h to return control to the calling program. The calling program can then take the appropriate action, which may include an orderly retreat and exit.

The example below illustrates the use of a custom error hook function (note also the Doxygen markup in some comment blocks):

/*
 * This example file demonstrates how to safely treat errors when
 * calling the glpk library.
 *
 * It creates a problem and alternatively adds 1 or -1 columns.
 * Trying to add -1 columns will cause the GLPK library to error.
 */

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>    /* provides the longjmp function */
#include "glpk.h"

void errorHook(void *in);
void buildModel(int forceError);

#define INFO struct sinfo

struct sinfo {
    char    *text;
    jmp_buf *env;
};

/*
 * This is the main function.
 */
int main(int argc, char** argv) {
    int i;
    printf("GLPK version: %s\n", glp_version());
    for (i = 1; i < 5; i++) {
        printf ("\nIteration %d", i);
        if (i & 1) {
            printf(", error expected to occur.\n");
        } else {
            printf(", success expected.\n");
        }
        if (runOptimizer(i)) {
            printf("An error has occured.\n");
        } else {
            printf("Successful execution.\n");
        }
    }
    return (EXIT_SUCCESS);
}

/**
 * This function secures calls to glpk with an error hook.
 * @param forceError force error if bit 0 = 1
 * @return ok code: 1 failure, 2 out of memory
 */
int runOptimizer(int forceError) {
    int ret = 0;
    INFO *info;
    info = (INFO*) malloc(sizeof(INFO));
    if (info == NULL) {
        return 2;
    }
    info->env = (jmp_buf *) malloc(sizeof(jmp_buf));
    if (info->env == NULL) {
        free(info);
        return 2;
    }
    info->text = "This information was passed to the hook function.";
    if (setjmp(*(info->env))) {
        printf("Post treatment of error.\n");
        ret = 1;
    } else {
        glp_error_hook(errorHook, info);
        buildModel(forceError);
    }
    glp_error_hook(NULL, NULL);
    free(info->env);
    free(info);
    return ret;
}

/**
 * Build a model with one column
 * @param forceError force error if bit 0 = 1
 */
void buildModel(int forceError) {
    glp_prob *lp;
    /* create problem */
    lp = glp_create_prob();
    if (forceError & 1) {
        /* add -1 column
         * this will cause an error.
         */
        glp_add_cols(lp, -1);
    } else {
        /* add 1 column */
        glp_add_cols(lp, 1);
    }
    /* delete problem */
    glp_delete_prob(lp);
}

/**
 * This hook function will be called if an error occurs when
 * calling the GLPK library.
 */
void errorHook(void *in) {
    INFO *info;
    info = (INFO *) in;
    printf("%s\n",info->text);
    /* free glpk memory */
    glp_free_env();
    /* safely return */
    longjmp(*(info->env), 1);
}

Catching and handling user interrupts edit

Users sometimes wish to terminate a running command-line program. This is normally achieved by hitting Ctrl-C which causes the operating system to send a SIGINT signal to the active program.

If the SIGINT is not caught and handled by the program, the system terminates the process more-or-less instantly. Programmers often like to offer a more graceful approach. GLPK provides the glp_error_hook hook function for this purpose. If you wish to terminate the solver midway through a solution, simply call the following from within this hook:

glp_error("%s\n", "Aborting due to user request");

If an MIP problem is running and you would like to let the current solution complete, then use:

glp_ios_terminate(tree);

The code for registering the hook function is not given here but further details can be found in this 2011 posting.

In GLPK for Java an error inside the GLPK library results in an exception of class org.gnu.glpk.GlpkException. Methods GLPK.glp_java_error() and GLPK.glp_ios_terminate() are provided. These can be called in terminal or callback listeners.