]> git.proxmox.com Git - mirror_ovs.git/blob - python/ovs/fatal_signal.py
73e4be6ad8f2f8e317393e437e22f6701b1badad
[mirror_ovs.git] / python / ovs / fatal_signal.py
1 # Copyright (c) 2010, 2011 Nicira, Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import atexit
16 import os
17 import signal
18 import sys
19
20 import ovs.vlog
21
22 _hooks = []
23 vlog = ovs.vlog.Vlog("fatal-signal")
24
25
26 def add_hook(hook, cancel, run_at_exit):
27 _init()
28 _hooks.append((hook, cancel, run_at_exit))
29
30
31 def fork():
32 """Clears all of the fatal signal hooks without executing them. If any of
33 the hooks passed a 'cancel' function to add_hook(), then those functions
34 will be called, allowing them to free resources, etc.
35
36 Following a fork, one of the resulting processes can call this function to
37 allow it to terminate without calling the hooks registered before calling
38 this function. New hooks registered after calling this function will take
39 effect normally."""
40 global _hooks
41 for hook, cancel, run_at_exit in _hooks:
42 if cancel:
43 cancel()
44
45 _hooks = []
46 \f
47 _added_hook = False
48 _files = {}
49
50
51 def add_file_to_unlink(file):
52 """Registers 'file' to be unlinked when the program terminates via
53 sys.exit() or a fatal signal."""
54 global _added_hook
55 if not _added_hook:
56 _added_hook = True
57 add_hook(_unlink_files, _cancel_files, True)
58 _files[file] = None
59
60
61 def remove_file_to_unlink(file):
62 """Unregisters 'file' from being unlinked when the program terminates via
63 sys.exit() or a fatal signal."""
64 if file in _files:
65 del _files[file]
66
67
68 def unlink_file_now(file):
69 """Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'.
70 Returns 0 if successful, otherwise a positive errno value."""
71 error = _unlink(file)
72 if error:
73 vlog.warn("could not unlink \"%s\" (%s)" % (file, os.strerror(error)))
74 remove_file_to_unlink(file)
75 return error
76
77
78 def _unlink_files():
79 for file_ in _files:
80 _unlink(file_)
81
82
83 def _cancel_files():
84 global _added_hook
85 global _files
86 _added_hook = False
87 _files = {}
88
89
90 def _unlink(file_):
91 try:
92 os.unlink(file_)
93 return 0
94 except OSError as e:
95 return e.errno
96
97 \f
98 def _signal_handler(signr, _):
99 _call_hooks(signr)
100
101 # Re-raise the signal with the default handling so that the program
102 # termination status reflects that we were killed by this signal.
103 signal.signal(signr, signal.SIG_DFL)
104 os.kill(os.getpid(), signr)
105
106
107 def _atexit_handler():
108 _call_hooks(0)
109
110
111 recurse = False
112
113
114 def _call_hooks(signr):
115 global recurse
116 if recurse:
117 return
118 recurse = True
119
120 for hook, cancel, run_at_exit in _hooks:
121 if signr != 0 or run_at_exit:
122 hook()
123
124
125 _inited = False
126
127
128 def _init():
129 global _inited
130 if not _inited:
131 _inited = True
132 if sys.platform == "win32":
133 signals = [signal.SIGTERM, signal.SIGINT]
134 else:
135 signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP,
136 signal.SIGALRM]
137
138 for signr in signals:
139 if signal.getsignal(signr) == signal.SIG_DFL:
140 signal.signal(signr, _signal_handler)
141 atexit.register(_atexit_handler)
142
143
144 def signal_alarm(timeout):
145 if sys.platform == "win32":
146 import os
147 import time
148 import threading
149
150 class Alarm (threading.Thread):
151 def __init__(self, timeout):
152 super(Alarm, self).__init__()
153 self.timeout = timeout
154 self.setDaemon(True)
155
156 def run(self):
157 time.sleep(self.timeout)
158 os._exit(1)
159
160 alarm = Alarm(timeout)
161 alarm.start()
162 else:
163 signal.alarm(timeout)