mirror of
https://github.com/ceph/ceph
synced 2024-12-23 20:03:56 +00:00
fdebf40f34
Each byte written to stdin will be interpreted as a signal. Signed-off-by: Sage Weil <sage@inktank.com>
85 lines
2.0 KiB
Python
Executable File
85 lines
2.0 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
"""
|
|
Helper script for running long-living processes.
|
|
|
|
(Name says daemon, but that is intended to mean "long-living", we
|
|
assume child process does not double-fork.)
|
|
|
|
We start the command passed as arguments, with /dev/null as stdin, and
|
|
then wait for EOF on stdin.
|
|
|
|
When EOF is seen on stdin, the child process is killed.
|
|
|
|
When the child process exits, this helper exits too.
|
|
"""
|
|
|
|
import fcntl
|
|
import os
|
|
import select
|
|
import signal
|
|
import struct
|
|
import subprocess
|
|
import sys
|
|
|
|
end_signal = signal.SIGKILL
|
|
if sys.argv[1] == "term":
|
|
end_signal = signal.SIGTERM
|
|
|
|
cmd_start = 2
|
|
|
|
nostdin = False
|
|
if sys.argv[cmd_start] == "nostdin":
|
|
nostdin = True
|
|
cmd_start += 1
|
|
|
|
proc = None
|
|
if nostdin:
|
|
proc = subprocess.Popen(
|
|
args=sys.argv[cmd_start:],
|
|
)
|
|
else:
|
|
with file('/dev/null', 'rb') as devnull:
|
|
proc = subprocess.Popen(
|
|
args=sys.argv[cmd_start:],
|
|
stdin=devnull,
|
|
)
|
|
|
|
flags = fcntl.fcntl(0, fcntl.F_GETFL)
|
|
fcntl.fcntl(0, fcntl.F_SETFL, flags | os.O_NDELAY)
|
|
|
|
saw_eof = False
|
|
while True:
|
|
r,w,x = select.select([0], [], [0], 0.2)
|
|
if r:
|
|
data = os.read(0, 1)
|
|
if not data:
|
|
saw_eof = True
|
|
proc.send_signal(end_signal)
|
|
break
|
|
else:
|
|
sig, = struct.unpack('!b', data)
|
|
proc.send_signal(sig)
|
|
|
|
if proc.poll() is not None:
|
|
# child exited
|
|
break
|
|
|
|
exitstatus = proc.wait()
|
|
if exitstatus > 0:
|
|
print >>sys.stderr, '{me}: command failed with exit status {exitstatus:d}'.format(
|
|
me=os.path.basename(sys.argv[0]),
|
|
exitstatus=exitstatus,
|
|
)
|
|
sys.exit(exitstatus)
|
|
elif exitstatus < 0:
|
|
if saw_eof and exitstatus == -end_signal:
|
|
# suppress error from the exit we intentionally caused
|
|
pass
|
|
else:
|
|
print >>sys.stderr, '{me}: command crashed with signal {signal:d}'.format(
|
|
me=os.path.basename(sys.argv[0]),
|
|
signal=-exitstatus,
|
|
)
|
|
sys.exit(1)
|