Etienne Perot  committed a91354f

Expand the try/except block that kills the children processes, add timeout parameter, test it with echo server test

  • Participants
  • Parent commits d56da88
  • Branches master

Comments (0)

Files changed (2)


 parser = optparse.OptionParser(usage='Usage: %prog -p port [options] /usr/bin/foo-serverd')
 parser.add_option('-p', '--port', dest='port', type='int', help='The port number that the subprocess will be listening on.', metavar='PORT')
 parser.add_option('-d', '--destination', dest='host', help='The destination hostname that the subprocess will be listening on. (Default: localhost)', default='localhost', metavar='HOSTNAME')
+parser.add_option('-k', '--kill-timeout', dest='timeout', type='int', help='The timeout after which the connection will be closed if no data has been passed in either direction. (Default: 10 seconds)', default=10, metavar='TIMEOUT')
 parser.add_option('-t', '--time-delay', dest='delay', type='int', help='The time it will take for the subprocess before it starts actually listening. Data will be buffered until this amount of time. (Default: 3 seconds)', default=3, metavar='DELAY')
 (option, args) = parser.parse_args()
 sys.stdout = sys.stdout.detach()
 class ProcessThread(threading.Thread):
-	def __init__(self, processConnection):
+	def __init__(self, processConnection, timeout):
 		self.processConnection = processConnection
+		self.timeout = timeout
 		self.daemon = True
+	def updateTimeout(self, data):
+		if len(data):
+			self.timeout.set(time.time())
+		return data
 class InetdToProcessThread(ProcessThread):
 	def run(self):
 		while True:
-			self.processConnection.sendall(
+			self.processConnection.sendall(self.updateTimeout(
 class ProcessToInetdThread(ProcessThread):
 	def run(self):
 		while True:
-			sys.stdout.write(self.processConnection.recv(1))
+			sys.stdout.write(self.updateTimeout(self.processConnection.recv(1)))
 process = subprocess.Popen(
 class ProcessStdoutConsumer(ProcessThread):
 	def run(self):
 		while True:
+			self.updateTimeout(
+class UnsafeMutableInt(object):
+	def __init__(self, value=0):
+		self.value = value
+	def get(self):
+		return self.value
+	def set(self, value):
+		self.value = value
 if option.delay > 0:
 if process.poll() is not None:
 	sys.exit(0) # Process ended before we could connect
-processConnection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-processConnection.connect((, option.port))
-processStdoutThread = ProcessStdoutConsumer(processConnection)
-inetdToProcessThread = InetdToProcessThread(processConnection)
-processToInetdThread = ProcessToInetdThread(processConnection)
+	processConnection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+	processConnection.connect((, option.port))
+	timeout = UnsafeMutableInt(time.time())
+	processStdoutThread = ProcessStdoutConsumer(processConnection, timeout)
+	inetdToProcessThread = InetdToProcessThread(processConnection, timeout)
+	processToInetdThread = ProcessToInetdThread(processConnection, timeout)
 	pollList = select.poll()
 	# Poll every relevant stream; if any of them has any error, stop everything.
 	[pollList.register(s) for s in [sys.stdin, sys.stdout, processConnection, process.stdin, process.stdout]]
 			if status & errorCondition:
 				keepGoing = False
+		if time.time() - timeout.get() > option.timeout:
+			break
 	if process.poll() is None: # Process is still alive, we must kill it.
 			os.killpg(, signal.SIGTERM) # Kill the process group
 			if process.poll() is None: # Still standing?

File testing/

 import sys, time
 def w(s):
-	sys.stdout.write(' ' + s + ' ')
-	sys.stdout.flush()
+	try:
+		sys.stdout.write(s + ' ')
+		sys.stdout.flush()
+	except:
+		sys.exit(0)
-[w(x) for x in 'Hello there! This is a test message.\n This is a message on another line.\n And here we have the third line.\n'.split(' ')]
+[w(x) for x in 'Hello there! This is a test message.\n This is a message on another line.\n And here we have the third line.\n Now we try to timeout...'.split(' ')]
+[w(x) for x in 'Should have timeouted by now. If that is not the case, there is a problem somewhere.'.split(' ')]