2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-25 19:10:10 +00:00

Fix handling of children in shellmodule plugins

Exit of a shell plugin was not handled correctly.  Fix that
This commit is contained in:
Jarrod Johnson 2014-05-28 12:25:13 -04:00
parent f525f054ba
commit b92487da24

View File

@ -35,6 +35,10 @@ import subprocess
class ExecConsole(conapi.Console):
def __init__(self, executable, node):
self.subproc = None
self._master = None
self._datacallback = None
self.readerthread = None
self.executable = executable
self.subenv = {
'TERM': 'xterm',
@ -42,17 +46,34 @@ class ExecConsole(conapi.Console):
}
def relaydata(self):
while 1:
select.select(
while self.subproc is not None:
rdylist, _, _ = select.select(
(self._master, self.subproc.stderr), (), (),
3600 + (random.random() * 120))
try:
while 1:
self._datacallback(os.read(self._master, 128))
eventlet.sleep(0)
except OSError as e:
if e.errno == 11:
pass
if self._master in rdylist:
try:
somedata = os.read(self._master, 128)
while somedata:
self._datacallback(somedata)
eventlet.sleep(0)
somedata = os.read(self._master, 128)
except OSError as e:
if e.errno != 11:
raise
if self.subproc.stderr in rdylist:
try:
somedata = self.subproc.stderr.read()
while somedata:
self._datacallback(somedata)
eventlet.sleep(0)
somedata = self.subproc.stderr.read()
except IOError as e:
if e.errno != 11:
raise
childstate = self.subproc.poll()
if childstate is not None:
self._datacallback(conapi.ConsoleEvent.Disconnect)
self.subproc = None
def connect(self, callback):
self._datacallback = callback
@ -61,18 +82,27 @@ class ExecConsole(conapi.Console):
self.subproc = subprocess.Popen(
[self.executable], env=self.subenv,
stdin=slave, stdout=slave,
stderr=subprocess.PIPE)
stderr=subprocess.PIPE, close_fds=True)
os.close(slave)
fcntl.fcntl(master, fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(self.subproc.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
self.readerthread = eventlet.spawn(self.relaydata)
def write(self, data):
self.subproc.stdin.write(data)
os.write(self._master, data)
def close(self):
if self.subproc is None or self.subproc.poll() is not None:
return
self.subproc.terminate()
eventlet.sleep(10)
self.subproc.kill()
waittime = 10
while self.subproc is not None or self.subproc.poll() is None:
eventlet.sleep(1)
waittime -= 1
if waittime == 0:
break
if self.subproc is not None and self.subproc.poll() is None:
self.subproc.kill()
class Plugin(object):