From: Phillip Berndt Date: Sun, 5 Jun 2016 19:15:37 +0000 (+0200) Subject: Merge branch 'retry_commands' X-Git-Tag: 1.0~20 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=7a41c28a93e2907a34d9a90e1821b2233e149642;hp=-c;p=deb_pkgs%2Fautorandr.git Merge branch 'retry_commands' --- 7a41c28a93e2907a34d9a90e1821b2233e149642 diff --combined autorandr.py index 0b16695,812329d..c8b8f8f --- a/autorandr.py +++ b/autorandr.py @@@ -23,6 -23,7 +23,6 @@@ # from __future__ import print_function -import time import binascii import copy @@@ -34,6 -35,6 +34,7 @@@ import r import subprocess import sys import shutil ++import time from collections import OrderedDict from distutils.version import LooseVersion as Version @@@ -112,8 -113,7 +113,8 @@@ class AutorandrException(Exception) retval.append(":\n ") retval.append(str(self.original_exception).replace("\n", "\n ")) if self.report_bug: - retval.append("\nThis appears to be a bug. Please help improving autorandr by reporting it upstream." + retval.append("\nThis appears to be a bug. Please help improving autorandr by reporting it upstream:" + "\nhttps://github.com/phillipberndt/autorandr/issues" "\nPlease attach the output of `xrandr --verbose` to your bug report if appropriate.") return "".join(retval) @@@ -529,6 -529,25 +530,25 @@@ def update_mtime(filename) except: return False + def call_and_retry(*args, **kwargs): + """Wrapper around subprocess.call that retries failed calls. + + This function calls subprocess.call and on non-zero exit states, + waits a second and then retries once. This mitigates #47, + a timing issue with some drivers. + """ + kwargs_redirected = dict(kwargs) + if hasattr(subprocess, "DEVNULL"): + kwargs_redirected["stdout"] = getattr(subprocess, "DEVNULL") + else: + kwargs_redirected["stdout"] = open(os.devnull, "w") + kwargs_redirected["stderr"] = kwargs_redirected["stdout"] + retval = subprocess.call(*args, **kwargs_redirected) + if retval != 0: + time.sleep(1) + retval = subprocess.call(*args, **kwargs) + return retval + def apply_configuration(new_configuration, current_configuration, dry_run=False): "Apply a configuration" outputs = sorted(new_configuration.keys(), key=lambda x: new_configuration[x].sort_key) @@@ -582,13 -601,13 +602,13 @@@ # Perform pe-change auxiliary changes if auxiliary_changes_pre: argv = base_argv + list(chain.from_iterable(auxiliary_changes_pre)) - if subprocess.call(argv) != 0: + if call_and_retry(argv) != 0: raise AutorandrException("Command failed: %s" % " ".join(argv)) # Disable unused outputs, but make sure that there always is at least one active screen disable_keep = 0 if remain_active_count else 1 if len(disable_outputs) > disable_keep: - if subprocess.call(base_argv + list(chain.from_iterable(disable_outputs[:-1] if disable_keep else disable_outputs))) != 0: + if call_and_retry(base_argv + list(chain.from_iterable(disable_outputs[:-1] if disable_keep else disable_outputs))) != 0: # Disabling the outputs failed. Retry with the next command: # Sometimes disabling of outputs fails due to an invalid RRSetScreenSize. # This does not occur if simultaneously the primary screen is reset. @@@ -607,7 -626,7 +627,7 @@@ operations = disable_outputs + enable_outputs for index in range(0, len(operations), 2): argv = base_argv + list(chain.from_iterable(operations[index:index+2])) - if subprocess.call(argv) != 0: + if call_and_retry(argv) != 0: raise AutorandrException("Command failed: %s" % " ".join(argv)) def is_equal_configuration(source_configuration, target_configuration): @@@ -926,5 -945,5 +946,5 @@@ if __name__ == '__main__' print("Exception: {0}".format(e.__class__.__name__)) sys.exit(2) - print("Unhandled exception ({0}). Please report this as a bug.".format(e), file=sys.stderr) + print("Unhandled exception ({0}). Please report this as a bug at https://github.com/phillipberndt/autorandr/issues.".format(e), file=sys.stderr) raise