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