Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: client/tests/kvm/scripts/virtio_console_guest.py

Issue 6883035: Merge remote branch 'autotest-upstream/master' into autotest-merge (Closed) Base URL: ssh://gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/tests/kvm/scripts/virtio_console_guest.py
diff --git a/client/tests/kvm/scripts/virtio_console_guest.py b/client/tests/kvm/scripts/virtio_console_guest.py
index 6626593ca3fbef82b0fcbce9ff52b4b79db2ba61..8f0bb9f522ece7d6dd2a0fc22e703f04c6163256 100755
--- a/client/tests/kvm/scripts/virtio_console_guest.py
+++ b/client/tests/kvm/scripts/virtio_console_guest.py
@@ -9,8 +9,8 @@ Auxiliary script used to send data between ports on guests.
"""
import threading
from threading import Thread
-import os, select, re, random, sys, array
-import fcntl, traceback, signal
+import os, select, re, random, sys, array, stat
+import fcntl, traceback, signal, time
DEBUGPATH = "/sys/kernel/debug"
SYSFSPATH = "/sys/class/virtio-ports/"
@@ -547,6 +547,7 @@ class VirtioGuest:
@param in_files: Array of input files.
@param out_files: Array of output files.
@param cachesize: Cachesize.
+ @param mode: Mode of switch.
"""
self.ports = self._get_port_status()
@@ -573,7 +574,7 @@ class VirtioGuest:
for desc in self.files.itervalues():
os.close(desc)
self.files.clear()
- print "PASS: All threads finished."
+ print "PASS: All threads finished"
def die(self):
@@ -702,7 +703,6 @@ def compile():
def guest_exit():
global exiting
exiting = True
- os.kill(os.getpid(), signal.SIGUSR1)
def worker(virt):
@@ -710,48 +710,220 @@ def worker(virt):
Worker thread (infinite) loop of virtio_guest.
"""
global exiting
- print "PASS: Start"
-
+ print "PASS: Daemon start."
+ p = select.poll()
+ p.register(sys.stdin.fileno())
while not exiting:
- str = raw_input()
- try:
- exec str
- except:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- print "On Guest exception from: \n" + "".join(
- traceback.format_exception(exc_type,
- exc_value,
- exc_traceback))
- print "FAIL: Guest command exception."
+ d = p.poll()
+ if (d[0][1] == select.POLLIN):
+ str = raw_input()
+ try:
+ exec str
+ except:
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ print "On Guest exception from: \n" + "".join(
+ traceback.format_exception(exc_type,
+ exc_value,
+ exc_traceback))
+ print "FAIL: Guest command exception."
+ elif (d[0][1] & select.POLLHUP):
+ time.sleep(0.5)
def sigusr_handler(sig, frame):
pass
+class Daemon:
+ """
+ Daemonize guest
+ """
+ def __init__(self, stdin, stdout, stderr):
+ """
+ Init daemon.
+
+ @param stdin: path to stdin file.
+ @param stdout: path to stdout file.
+ @param stderr: path to stderr file.
+ """
+ self.stdin = stdin
+ self.stdout = stdout
+ self.stderr = stderr
+
+
+ @staticmethod
+ def is_file_open(path):
+ """
+ Determine process which open file.
+
+ @param path: Path to file.
+ @return [[pid,mode], ... ].
+ """
+ opens = []
+ pids = os.listdir('/proc')
+ for pid in sorted(pids):
+ try:
+ int(pid)
+ except ValueError:
+ continue
+ fd_dir = os.path.join('/proc', pid, 'fd')
+ try:
+ for file in os.listdir(fd_dir):
+ try:
+ p = os.path.join(fd_dir, file)
+ link = os.readlink(os.path.join(fd_dir, file))
+ if link == path:
+ mode = os.lstat(p).st_mode
+ opens.append([pid, mode])
+ except OSError:
+ continue
+ except OSError, e:
+ if e.errno == 2:
+ continue
+ raise
+ return opens
+
+
+ def daemonize(self):
+ """
+ Run guest as a daemon.
+ """
+ try:
+ pid = os.fork()
+ if pid > 0:
+ return False
+ except OSError, e:
+ sys.stderr.write("Daemonize failed: %s\n" % (e))
+ sys.exit(1)
+
+ os.chdir("/")
+ os.setsid()
+ os.umask(0)
+
+ try:
+ pid = os.fork()
+ if pid > 0:
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("Daemonize failed: %s\n" % (e))
+ sys.exit(1)
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+ si = file(self.stdin,'r')
+ so = file(self.stdout,'w')
+ se = file(self.stderr,'w')
+
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+
+ sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+ sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
+ return True
+
+
+ def start(self):
+ """
+ Start the daemon
+
+ @return: PID of daemon.
+ """
+ # Check for a pidfile to see if the daemon already runs
+ openers = self.is_file_open(self.stdout)
+ rundaemon = False
+ if len(openers) > 0:
+ for i in openers:
+ if i[1] & stat.S_IWUSR:
+ rundaemon = True
+ openers.remove(i)
+ if len(openers) > 0:
+ for i in openers:
+ os.kill(int(i[0]), 9)
+ time.sleep(0.3)
+
+ # Start the daemon
+ if not rundaemon:
+ if self.daemonize():
+ self.run()
+
+
+ def run(self):
+ """
+ Run guest main thread
+ """
+ global exiting
+ virt = VirtioGuest()
+ slave = Thread(target=worker, args=(virt, ))
+ slave.start()
+ signal.signal(signal.SIGUSR1, sigusr_handler)
+ signal.signal(signal.SIGALRM, sigusr_handler)
+ while not exiting:
+ signal.alarm(1)
+ signal.pause()
+ catch = virt.catching_signal()
+ if catch:
+ signal.signal(signal.SIGIO, virt)
+ elif catch is False:
+ signal.signal(signal.SIGIO, signal.SIG_DFL)
+ if catch is not None:
+ virt.use_config.set()
+ print "PASS: guest_exit"
+ sys.exit(0)
+
+
def main():
"""
Main function with infinite loop to catch signal from system.
"""
if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
compile()
+ stdin = "/tmp/guest_daemon_pi"
+ stdout = "/tmp/guest_daemon_po"
+ stderr = "/tmp/guest_daemon_pe"
- global exiting
- virt = VirtioGuest()
- slave = Thread(target=worker, args=(virt, ))
- slave.start()
- signal.signal(signal.SIGUSR1, sigusr_handler)
- while not exiting:
- signal.pause()
- catch = virt.catching_signal()
- if catch:
- signal.signal(signal.SIGIO, virt)
- elif catch is False:
- signal.signal(signal.SIGIO, signal.SIG_DFL)
- if catch is not None:
- virt.use_config.set()
- print "PASS: guest_exit"
+ for f in [stdin, stdout, stderr]:
+ try:
+ os.mkfifo(f)
+ except OSError, e:
+ if e.errno == 17:
+ pass
+
+ daemon = Daemon(stdin,
+ stdout,
+ stderr)
+ daemon.start()
+
+ d_stdin = os.open(stdin, os.O_WRONLY)
+ d_stdout = os.open(stdout, os.O_RDONLY)
+ d_stderr = os.open(stderr, os.O_RDONLY)
+
+ s_stdin = sys.stdin.fileno()
+ s_stdout = sys.stdout.fileno()
+ s_stderr = sys.stderr.fileno()
+
+ pid = filter(lambda x: x[0] != str(os.getpid()),
+ daemon.is_file_open(stdout))[0][0]
+
+ print "PASS: Start"
+ while 1:
+ ret = select.select([d_stderr,
+ d_stdout,
+ s_stdin],
+ [], [], 1.0)
+ if s_stdin in ret[0]:
+ os.write(d_stdin,os.read(s_stdin, 1))
+ if d_stdout in ret[0]:
+ os.write(s_stdout,os.read(d_stdout, 1024))
+ if d_stderr in ret[0]:
+ os.write(s_stderr,os.read(d_stderr, 1024))
+ if not os.path.exists("/proc/" + pid):
+ sys.exit(0)
+
+ os.close(d_stdin)
+ os.close(d_stdout)
+ os.close(d_stderr)
if __name__ == "__main__":
main()

Powered by Google App Engine
This is Rietveld 408576698