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