Scippy

    SCIP

    Solving Constraint Integer Programs

    interrupt.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file interrupt.c
    26 * @ingroup OTHER_CFILES
    27 * @brief methods and datastructures for catching the user CTRL-C interrupt
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include <assert.h>
    34#include <sys/types.h>
    35#include <stdlib.h>
    36#include <signal.h>
    37
    38#include "scip/def.h"
    39#include "scip/pub_message.h"
    41#include "scip/interrupt.h"
    42
    43
    44static volatile
    45int ninterrupts = 0; /**< static variable counting the number of CTRL-C interrupts */
    46static volatile
    47int nterms = 0; /**< static variable counting the number of times that the process received a SIGTERM signal */
    48
    49
    50#ifdef SCIP_NO_SIGACTION
    51typedef void (*SigHdlr)(int);
    52
    53/** CTRL-C interrupt data */
    54struct SCIP_Interrupt
    55{
    56 SigHdlr oldsighdlr; /**< old CTRL-C interrupt handler */
    57 int nuses; /**< number of times, the interrupt is captured */
    58};
    59
    60#else
    61
    62/** CTRL-C interrupt data */
    64{
    65 struct sigaction oldsigaction; /**< old CTRL-C interrupt handler */
    66 int nuses; /**< number of times, the interrupt is captured */
    67};
    68#endif
    69
    70/** interrupt handler for CTRL-C interrupts */
    71static
    73 int signum /**< interrupt signal number */
    74 )
    75{
    77
    79 if( ninterrupts >= 5 )
    80 {
    81 printf("pressed CTRL-C %d times. forcing termination.\n", ninterrupts);
    82 exit(1);
    83 }
    84 else
    85 {
    86 printf("pressed CTRL-C %d times (5 times for forcing termination)\n", ninterrupts);
    87 }
    88}
    89
    90/** creates a CTRL-C interrupt data */
    92 SCIP_INTERRUPT** interrupt /**< pointer to store the CTRL-C interrupt data */
    93 )
    94{
    95 assert(interrupt != NULL);
    96
    97 SCIP_ALLOC( BMSallocMemory(interrupt) );
    98 (*interrupt)->nuses = 0;
    99
    100 return SCIP_OKAY;
    101}
    102
    103/** frees a CTRL-C interrupt data */
    105 SCIP_INTERRUPT** interrupt /**< pointer to the CTRL-C interrupt data */
    106 )
    107{
    108 assert(interrupt != NULL);
    109
    110 BMSfreeMemory(interrupt);
    111}
    112
    113/** captures the CTRL-C interrupt to call the SCIP's own interrupt handler */
    115 SCIP_INTERRUPT* interrupt /**< CTRL-C interrupt data */
    116 )
    117{
    118 assert(interrupt != NULL);
    119 assert(interrupt->nuses >= 0);
    120
    121 if( interrupt->nuses == 0 )
    122 {
    123#ifdef SCIP_NO_SIGACTION
    124 interrupt->oldsighdlr = signal(SIGINT, interruptHandler);
    125#else
    126 struct sigaction newaction;
    127
    128 /* initialize new signal action */
    129 newaction.sa_handler = interruptHandler;
    130 newaction.sa_flags = 0;
    131 (void)sigemptyset(&newaction.sa_mask);
    132
    133 /* set new signal action, and remember old one */
    134 (void)sigaction(SIGINT, &newaction, &interrupt->oldsigaction);
    135#endif
    136
    137 ninterrupts = 0;
    138 nterms = 0;
    139 }
    140 interrupt->nuses++;
    141}
    142
    143/** releases the CTRL-C interrupt and restores the old interrupt handler */
    145 SCIP_INTERRUPT* interrupt /**< CTRL-C interrupt data */
    146 )
    147{
    148 assert(interrupt != NULL);
    149 assert(interrupt->nuses >= 1);
    150
    151 interrupt->nuses--;
    152 if( interrupt->nuses == 0 )
    153 {
    154#ifdef SCIP_NO_SIGACTION
    155 (void)signal(SIGINT, interrupt->oldsighdlr);
    156#else
    157 (void)sigaction(SIGINT, &interrupt->oldsigaction, NULL);
    158#endif
    159 }
    160}
    161
    162/** returns whether the user interrupted by pressing CTRL-C */
    164 void
    165 )
    166{
    167 return (ninterrupts > 0);
    168}
    169
    170/** returns whether a process termination signal was received */
    172 void
    173 )
    174{
    175 return (nterms > 0);
    176}
    177
    178/** sends a termination signal to all SCIP processes so that they try to terminate as soon as possible
    179 *
    180 * @note For terminating a specific SCIP process use SCIPinterruptSolve().
    181 */
    183 void
    184 )
    185{
    186 nterms++;
    187}
    188
    189/** resets the number of interrupts to 0 */
    191 void
    192 )
    193{
    194 ninterrupts = 0;
    195 nterms = 0;
    196}
    197
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_UNUSED(x)
    Definition: def.h:409
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    SCIP_RETCODE SCIPinterruptCreate(SCIP_INTERRUPT **interrupt)
    Definition: interrupt.c:91
    void SCIPinterruptRelease(SCIP_INTERRUPT *interrupt)
    Definition: interrupt.c:144
    static volatile int nterms
    Definition: interrupt.c:47
    void SCIPresetInterrupted(void)
    Definition: interrupt.c:190
    static volatile int ninterrupts
    Definition: interrupt.c:45
    void SCIPinterruptCapture(SCIP_INTERRUPT *interrupt)
    Definition: interrupt.c:114
    void SCIPinterruptFree(SCIP_INTERRUPT **interrupt)
    Definition: interrupt.c:104
    static void interruptHandler(int signum)
    Definition: interrupt.c:72
    void SCIPtryTerminate(void)
    Definition: interrupt.c:182
    SCIP_Bool SCIPterminated(void)
    Definition: interrupt.c:171
    SCIP_Bool SCIPinterrupted(void)
    Definition: interrupt.c:163
    methods for catching the user CTRL-C interrupt
    memory allocation routines
    #define BMSfreeMemory(ptr)
    Definition: memory.h:145
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    public methods for message output
    struct sigaction oldsigaction
    Definition: interrupt.c:65
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63