|
50 | 50 | from devlib.exception import (DevlibTransientError, TargetStableError,
|
51 | 51 | TargetNotRespondingError, TimeoutError,
|
52 | 52 | TargetTransientError, KernelConfigKeyError,
|
53 |
| - TargetError, HostError) # pylint: disable=redefined-builtin |
| 53 | + TargetError, HostError, TargetCalledProcessError) # pylint: disable=redefined-builtin |
54 | 54 | from devlib.utils.ssh import SshConnection
|
55 | 55 | from devlib.utils.android import AdbConnection, AndroidProperties, LogcatMonitor, adb_command, adb_disconnect, INTENT_FLAGS
|
56 | 56 | from devlib.utils.misc import memoized, isiterable, convert_new_lines
|
@@ -736,12 +736,43 @@ def batch_revertable_write_value(self, kwargs_list):
|
736 | 736 |
|
737 | 737 | def write_value(self, path, value, verify=True):
|
738 | 738 | value = str(value)
|
739 |
| - self.execute('echo {} > {}'.format(quote(value), quote(path)), check_exit_code=False, as_root=True) |
| 739 | + |
740 | 740 | if verify:
|
741 |
| - output = self.read_value(path) |
742 |
| - if not output == value: |
743 |
| - message = 'Could not set the value of {} to "{}" (read "{}")'.format(path, value, output) |
| 741 | + # Check in a loop for a while since updates to sysfs files can take |
| 742 | + # some time to be observed, typically when a write triggers a |
| 743 | + # lengthy kernel-side request, and the read is based on some piece |
| 744 | + # of state that may take some time to be updated by the write |
| 745 | + # request, such as hotplugging a CPU. |
| 746 | + cmd = ''' |
| 747 | +orig=$(cat {path} 2>/dev/null || printf "") |
| 748 | +printf "%s" {value} > {path} || exit 10 |
| 749 | +if [ {value} != "$orig" ]; then |
| 750 | + trials=0 |
| 751 | + while [ "$(cat {path} 2>/dev/null)" != {value} ]; do |
| 752 | + if [ $trials -ge 10 ]; then |
| 753 | + cat {path} |
| 754 | + exit 11 |
| 755 | + fi |
| 756 | + sleep 0.01 |
| 757 | + trials=$((trials + 1)) |
| 758 | + done |
| 759 | +fi |
| 760 | +''' |
| 761 | + else: |
| 762 | + cmd = 'printf "%s" {value} > {path}' |
| 763 | + cmd = cmd.format(path=quote(path), value=quote(value)) |
| 764 | + |
| 765 | + try: |
| 766 | + self.execute(cmd, check_exit_code=True, as_root=True) |
| 767 | + except TargetCalledProcessError as e: |
| 768 | + if e.returncode == 10: |
| 769 | + raise TargetStableError(f'Could not write "{value}" to {path}: {e.output}') |
| 770 | + elif verify and e.returncode == 11: |
| 771 | + out = e.output |
| 772 | + message = 'Could not set the value of {} to "{}" (read "{}")'.format(path, value, out) |
744 | 773 | raise TargetStableError(message)
|
| 774 | + else: |
| 775 | + raise |
745 | 776 |
|
746 | 777 | def reset(self):
|
747 | 778 | try:
|
|
0 commit comments