OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # Virtual Me2Me implementation. This script runs and manages the processes | 6 # Virtual Me2Me implementation. This script runs and manages the processes |
7 # required for a Virtual Me2Me desktop, which are: X server, X desktop | 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop |
8 # session, and Host process. | 8 # session, and Host process. |
9 # This script is intended to run continuously as a background daemon | 9 # This script is intended to run continuously as a background daemon |
10 # process, running under an ordinary (non-root) user account. | 10 # process, running under an ordinary (non-root) user account. |
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 os.dup2(log_fd, sys.stderr.fileno()) | 627 os.dup2(log_fd, sys.stderr.fileno()) |
628 | 628 |
629 # Close the temporary file-descriptors. | 629 # Close the temporary file-descriptors. |
630 os.close(devnull_fd) | 630 os.close(devnull_fd) |
631 os.close(log_fd) | 631 os.close(log_fd) |
632 | 632 |
633 | 633 |
634 def cleanup(): | 634 def cleanup(): |
635 logging.info("Cleanup.") | 635 logging.info("Cleanup.") |
636 | 636 |
637 global g_pidfile | |
637 if g_pidfile: | 638 if g_pidfile: |
638 try: | 639 try: |
639 g_pidfile.delete_file() | 640 g_pidfile.delete_file() |
641 g_pidfile = None | |
640 except Exception, e: | 642 except Exception, e: |
641 logging.error("Unexpected error deleting PID file: " + str(e)) | 643 logging.error("Unexpected error deleting PID file: " + str(e)) |
642 | 644 |
645 global g_desktops | |
643 for desktop in g_desktops: | 646 for desktop in g_desktops: |
644 if desktop.x_proc: | 647 if desktop.x_proc: |
645 logging.info("Terminating Xvfb") | 648 logging.info("Terminating Xvfb") |
646 desktop.x_proc.terminate() | 649 desktop.x_proc.terminate() |
650 g_desktops = [] | |
647 | 651 |
648 | 652 |
649 def reload_config(): | 653 def reload_config(): |
650 for desktop in g_desktops: | 654 for desktop in g_desktops: |
651 if desktop.host_proc: | 655 if desktop.host_proc: |
652 # Terminating the Host will cause the main loop to spawn another | 656 # Terminating the Host will cause the main loop to spawn another |
653 # instance, which will read any changes made to the Host config file. | 657 # instance, which will read any changes made to the Host config file. |
654 desktop.host_proc.terminate() | 658 desktop.host_proc.terminate() |
655 | 659 |
656 | 660 |
657 def signal_handler(signum, stackframe): | 661 def signal_handler(signum, stackframe): |
658 if signum == signal.SIGUSR1: | 662 if signum == signal.SIGUSR1: |
659 logging.info("SIGUSR1 caught, reloading configuration.") | 663 logging.info("SIGUSR1 caught, reloading configuration.") |
660 reload_config() | 664 reload_config() |
661 else: | 665 else: |
662 # Exit cleanly so the atexit handler, cleanup(), gets called. | 666 # Exit cleanly so the atexit handler, cleanup(), gets called. |
663 raise SystemExit | 667 raise SystemExit |
664 | 668 |
665 | 669 |
670 def relaunch_self(): | |
671 cleanup() | |
672 os.execvp(sys.argv[0], sys.argv) | |
673 | |
674 | |
666 def main(): | 675 def main(): |
667 DEFAULT_SIZE = "1280x800" | 676 DEFAULT_SIZE = "1280x800" |
668 parser = optparse.OptionParser( | 677 parser = optparse.OptionParser( |
669 "Usage: %prog [options] [ -- [ X server options ] ]") | 678 "Usage: %prog [options] [ -- [ X server options ] ]") |
670 parser.add_option("-s", "--size", dest="size", action="append", | 679 parser.add_option("-s", "--size", dest="size", action="append", |
671 help="dimensions of virtual desktop (default: %s). " | 680 help="dimensions of virtual desktop (default: %s). " |
672 "This can be specified multiple times to make multiple " | 681 "This can be specified multiple times to make multiple " |
673 "screen resolutions available (if the Xvfb server " | 682 "screen resolutions available (if the Xvfb server " |
674 "supports this)" % DEFAULT_SIZE) | 683 "supports this)" % DEFAULT_SIZE) |
675 parser.add_option("-f", "--foreground", dest="foreground", default=False, | 684 parser.add_option("-f", "--foreground", dest="foreground", default=False, |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 | 875 |
867 desktop = Desktop(sizes) | 876 desktop = Desktop(sizes) |
868 | 877 |
869 # Remember the time when the last session was launched, in order to enforce | 878 # Remember the time when the last session was launched, in order to enforce |
870 # a minimum time between launches. This avoids spinning in case of a | 879 # a minimum time between launches. This avoids spinning in case of a |
871 # misconfigured system, or other error that prevents a session from starting | 880 # misconfigured system, or other error that prevents a session from starting |
872 # properly. | 881 # properly. |
873 last_launch_time = 0 | 882 last_launch_time = 0 |
874 | 883 |
875 while True: | 884 while True: |
876 # If the session process stops running (e.g. because the user logged out), | 885 # If the session process or X server stops running (e.g. because the user |
877 # the X server should be reset and the session restarted, to provide a | 886 # logged out), re-run this script with its original arguments. Since the |
878 # completely clean new session. | 887 # user's desktop is already gone at this point, there's no state to lose |
888 # so now is a good time to pick up any updates to this script that might | |
889 # have been installed. | |
879 if desktop.session_proc is None and desktop.x_proc is not None: | 890 if desktop.session_proc is None and desktop.x_proc is not None: |
880 logging.info("Terminating X server") | 891 logging.info("Terminating X server") |
881 desktop.x_proc.terminate() | 892 desktop.x_proc.terminate() |
893 relaunch_self() | |
894 elif desktop.x_proc is None and desktop.session_proc is not None: | |
895 logging.info("Terminating X session") | |
896 desktop.session_proc.terminate() | |
897 relaunch_self() | |
Lambros
2012/08/18 00:06:50
Unfortunately, calling relaunch_self() here (or ab
Jamie
2012/08/20 19:46:05
Good catch! Done.
| |
882 | 898 |
883 if desktop.x_proc is None: | 899 if desktop.x_proc is None and desktop.session_proc is None: |
884 if desktop.session_proc is not None: | 900 # Neither X server nor X session are running. |
885 # The X session would probably die soon if the X server is not | 901 elapsed = time.time() - last_launch_time |
886 # running (because of the loss of the X connection). Terminate it | 902 if elapsed < 60: |
887 # anyway, to be sure. | 903 logging.error("The session lasted less than 1 minute. Waiting " + |
888 logging.info("Terminating X session") | 904 "before starting new session.") |
889 desktop.session_proc.terminate() | 905 time.sleep(60 - elapsed) |
890 else: | |
891 # Neither X server nor X session are running. | |
892 elapsed = time.time() - last_launch_time | |
893 if elapsed < 60: | |
894 logging.error("The session lasted less than 1 minute. Waiting " + | |
895 "before starting new session.") | |
896 time.sleep(60 - elapsed) | |
897 | 906 |
898 logging.info("Launching X server and X session") | 907 logging.info("Launching X server and X session") |
899 last_launch_time = time.time() | 908 last_launch_time = time.time() |
900 desktop.launch_x_server(args) | 909 desktop.launch_x_server(args) |
901 desktop.launch_x_session() | 910 desktop.launch_x_session() |
902 | 911 |
903 if desktop.host_proc is None: | 912 if desktop.host_proc is None: |
904 logging.info("Launching host process") | 913 logging.info("Launching host process") |
905 desktop.launch_host(host_config) | 914 desktop.launch_host(host_config) |
906 | 915 |
907 try: | 916 try: |
908 pid, status = os.wait() | 917 pid, status = os.wait() |
909 except OSError, e: | 918 except OSError, e: |
910 if e.errno == errno.EINTR: | 919 if e.errno == errno.EINTR: |
911 # Retry on EINTR, which can happen if a signal such as SIGUSR1 is | 920 # Retry on EINTR, which can happen if a signal such as SIGUSR1 is |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
955 return 0 | 964 return 0 |
956 elif os.WEXITSTATUS(status) == 5: | 965 elif os.WEXITSTATUS(status) == 5: |
957 logging.info("Host domain is blocked by policy - exiting.") | 966 logging.info("Host domain is blocked by policy - exiting.") |
958 os.remove(host.config_file) | 967 os.remove(host.config_file) |
959 return 0 | 968 return 0 |
960 # Nothing to do for Mac-only status 6 (login screen unsupported) | 969 # Nothing to do for Mac-only status 6 (login screen unsupported) |
961 | 970 |
962 if __name__ == "__main__": | 971 if __name__ == "__main__": |
963 logging.basicConfig(level=logging.DEBUG) | 972 logging.basicConfig(level=logging.DEBUG) |
964 sys.exit(main()) | 973 sys.exit(main()) |
OLD | NEW |