ceph/teuthology/task/daemon-helper
Sam Lang c0f1ef7373 task/daemon-helper: Add nostdin option
Some daemons (smbd) will try to read from stdin and check if its a
socket, using that for sending/receiving messages.  If /dev/null is
used for stdin, the daemon aborts.  This patch adds a 'nostdin' option
to the daemon-helper so that the daemon can be started without /dev/null
as stdin.

Signed-off-by: Sam Lang <sam.lang@inktank.com>
2013-05-06 17:37:25 -07:00

81 lines
1.9 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 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
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)