Commit 1d7a64d6 authored by rgaudin's avatar rgaudin
Browse files

Fixed #223: prevent system from sleeping at begining of the process and restores it afterwards

parent ac3d0a59
2.0-rc7
* Fixed catalog update in Qemu (stage 5)
* Better SD-card writer (faster, error-handling, cancellable)
* Additional delays between download retries
* Prevents system from sleeping to avoid side effects
2.0-rc6
* JSON Exports's properties and sub-properties saved in a fixed order
......
......@@ -8,6 +8,23 @@ import subprocess
from util import CLILogger, ONE_MiB, human_readable_size
# windows-only flags to prevent sleep on executing thread
WINDOWS_SLEEP_FLAGS = {
# Enables away mode. This value must be specified with ES_CONTINUOUS.
# Away mode should be used only by media-recording and media-distribution
# applications that must perform critical background processing
# on desktop computers while the computer appears to be sleeping.
'ES_AWAYMODE_REQUIRED': 0x00000040,
# Informs the system that the state being set should remain in effect until
# the next call that uses ES_CONTINUOUS and one of the other state flags is cleared.
'ES_CONTINUOUS': 0x80000000,
# Forces the display to be on by resetting the display idle timer.
'ES_DISPLAY_REQUIRED': 0x00000002,
# Forces the system to be in the working state by resetting the system idle timer.
'ES_SYSTEM_REQUIRED': 0x00000001,
}
class CheckCallException(Exception):
def __init__(self, msg):
Exception(self, msg)
......@@ -235,3 +252,65 @@ class ImageWriterThread(threading.Thread):
if not self._should_stop:
os.fsync(device_fd)
close_handles(image_fd, device_fd)
def prevent_sleep(logger):
if sys.platform == "win32":
logger.std("Setting ES_SYSTEM_REQUIRED mode to current thread")
ctypes.windll.kernel32.SetThreadExecutionState(
WINDOWS_SLEEP_FLAGS['ES_CONTINUOUS'] |
WINDOWS_SLEEP_FLAGS['ES_SYSTEM_REQUIRED'] |
WINDOWS_SLEEP_FLAGS['ES_DISPLAY_REQUIRED'])
return
if sys.platform == "linux":
def make_unmapped_window(wm_name):
from Xlib import display
screen = display.Display().screen()
window = screen.root.create_window(0, 0, 1, 1, 0, screen.root_depth)
window.set_wm_name(wm_name)
window.set_wm_protocols([])
return window
logger.std("Suspending xdg-screensaver")
wid = None
try:
# Create window to use with xdg-screensaver
window = make_unmapped_window("caffeinate")
wid = hex(window.id)
cmd = ['/usr/bin/xdg-screensaver', 'suspend', wid]
logger.std("Calling {}".format(cmd))
p = subprocess.Popen(" ".join(cmd), shell=True)
p.wait()
if not p.returncode == 0:
raise OSError("xdg-screensaver returned {}".format(p.returncode))
except Exception as exp:
logger.err("Unable to disable sleep. Please do it manually.")
return wid
if sys.platform == "darwin":
cmd = ["/usr/bin/caffeinate", "-dsi"]
logger.std("Calling {}".format(cmd))
process = subprocess.Popen(cmd, **startup_info_args())
return process
def restore_sleep_policy(reference, logger):
if sys.platform == "win32":
logger.std("Restoring ES_CONTINUOUS mode to current thread")
ctypes.windll.kernel32.SetThreadExecutionState(
WINDOWS_SLEEP_FLAGS['ES_CONTINUOUS'])
return
if sys.platform == "linux":
logger.std("Resuming xdg-screensaver (wid #{})".format(reference))
if reference is not None:
subprocess_pretty_call(
['/usr/bin/xdg-screensaver', 'resume', reference], logger)
return
if sys.platform == "darwin":
logger.std("Stopping caffeinate process #{}".format(reference.pid))
reference.kill()
reference.wait(5)
return
......@@ -6,7 +6,7 @@ from backend.content import (get_collection, get_content,
from backend.download import download_content, unzip_file
from backend.mount import mount_data_partition, unmount_data_partition, test_mount_procedure, format_data_partition, guess_next_loop_device
from backend.mount import can_write_on, allow_write_on, restore_mode
from backend.util import subprocess_pretty_check_call, subprocess_pretty_call
from backend.util import subprocess_pretty_check_call, prevent_sleep, restore_sleep_policy
from backend.util import ensure_card_written, ImageWriterThread
from backend.sysreq import host_matches_requirements, requirements_url
import data
......@@ -28,6 +28,9 @@ def run_installation(name, timezone, language, wifi_pwd, admin_account, kalite,
cache_folder = get_cache(build_dir)
try:
logger.std("Preventing system from sleeping")
sleep_ref = prevent_sleep(logger)
logger.step("Check System Requirements")
logger.std("Please read {} for details".format(requirements_url))
sysreq_ok, missing_deps = host_matches_requirements(build_dir)
......@@ -345,6 +348,9 @@ def run_installation(name, timezone, language, wifi_pwd, admin_account, kalite,
logger.complete()
error = None
finally:
logger.std("Restoring system sleep policy")
restore_sleep_policy(sleep_ref, logger)
if sys.platform == "linux" and loop_dev and previous_loop_mode:
logger.step("Restoring loop device ({}) mode".format(loop_dev))
restore_mode(loop_dev, previous_loop_mode, logger)
......
......@@ -17,3 +17,4 @@ path.py==11.0
psutil==5.4.5
humanfriendly==4.12
requests==2.18.4
xlib==0.21
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment