Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.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
19 import ovs.vlog
20
21 _hooks = []
22 vlog = ovs.vlog.Vlog("fatal-signal")
23
24
25 def add_hook(hook, cancel, run_at_exit):
26     _init()
27     _hooks.append((hook, cancel, run_at_exit))
28
29
30 def fork():
31     """Clears all of the fatal signal hooks without executing them.  If any of
32     the hooks passed a 'cancel' function to add_hook(), then those functions
33     will be called, allowing them to free resources, etc.
34
35     Following a fork, one of the resulting processes can call this function to
36     allow it to terminate without calling the hooks registered before calling
37     this function.  New hooks registered after calling this function will take
38     effect normally."""
39     global _hooks
40     for hook, cancel, run_at_exit in _hooks:
41         if cancel:
42             cancel()
43
44     _hooks = []
45 \f
46 _added_hook = False
47 _files = {}
48
49
50 def add_file_to_unlink(file):
51     """Registers 'file' to be unlinked when the program terminates via
52     sys.exit() or a fatal signal."""
53     global _added_hook
54     if not _added_hook:
55         _added_hook = True
56         add_hook(_unlink_files, _cancel_files, True)
57     _files[file] = None
58
59
60 def remove_file_to_unlink(file):
61     """Unregisters 'file' from being unlinked when the program terminates via
62     sys.exit() or a fatal signal."""
63     if file in _files:
64         del _files[file]
65
66
67 def unlink_file_now(file):
68     """Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'.
69     Returns 0 if successful, otherwise a positive errno value."""
70     error = _unlink(file)
71     if error:
72         vlog.warn("could not unlink \"%s\" (%s)" % (file, os.strerror(error)))
73     remove_file_to_unlink(file)
74     return error
75
76
77 def _unlink_files():
78     for file_ in _files:
79         _unlink(file_)
80
81
82 def _cancel_files():
83     global _added_hook
84     global _files
85     _added_hook = False
86     _files = {}
87
88
89 def _unlink(file_):
90     try:
91         os.unlink(file_)
92         return 0
93     except OSError, e:
94         return e.errno
95
96 \f
97 def _signal_handler(signr, _):
98     _call_hooks(signr)
99
100     # Re-raise the signal with the default handling so that the program
101     # termination status reflects that we were killed by this signal.
102     signal.signal(signr, signal.SIG_DFL)
103     os.kill(os.getpid(), signr)
104
105
106 def _atexit_handler():
107     _call_hooks(0)
108
109
110 recurse = False
111
112
113 def _call_hooks(signr):
114     global recurse
115     if recurse:
116         return
117     recurse = True
118
119     for hook, cancel, run_at_exit in _hooks:
120         if signr != 0 or run_at_exit:
121             hook()
122
123
124 _inited = False
125
126
127 def _init():
128     global _inited
129     if not _inited:
130         _inited = True
131
132         for signr in (signal.SIGTERM, signal.SIGINT,
133                       signal.SIGHUP, signal.SIGALRM):
134             if signal.getsignal(signr) == signal.SIG_DFL:
135                 signal.signal(signr, _signal_handler)
136         atexit.register(_atexit_handler)