Fix crashes and improve hybrid mode handling in EnvyControl#234
Fix crashes and improve hybrid mode handling in EnvyControl#234vjaykrsna wants to merge 2 commits intobayasdev:mainfrom
Conversation
If xrandr exits with a non-zero code the except block logged a warning but execution fell through to the pattern.findall() call, where xrandr_output was never assigned, causing an immediate NameError crash. Return None explicitly so callers receive the expected sentinel value.
Two related bugs caused envycontrol to crash with 'Could not find Nvidia
GPU' even when switching to a mode that doesn't need the GPU visible:
1. get_current_mode() required BOTH the blacklist file AND the udev
removal rule to report 'integrated'. If only the udev rule existed
(e.g. after a partial or interrupted previous switch), the function
returned 'hybrid', misleading the CachedConfig adapter.
Fix: any single EnvyControl-specific integrated-mode file is now
sufficient to report integrated mode, since all three paths
(/etc/modprobe.d/blacklist-nvidia.conf,
/etc/udev/rules.d/50-remove-nvidia.rules,
/lib/udev/rules.d/50-remove-nvidia.rules)
are written exclusively by envycontrol for that mode.
2. CachedConfig.adapter() called create_cache_file() whenever the
current mode was detected as hybrid, including when the requested
switch target was also hybrid. create_cache_file() calls
get_nvidia_gpu_pci_bus() which parses lspci output; if a stale udev
removal rule was hiding the NVIDIA device the function called
sys.exit(1), aborting before cleanup() ever ran.
Fix: skip cache creation when the target switch is 'hybrid', since
hybrid mode never consumes the cached PCI bus value.
There was a problem hiding this comment.
Pull request overview
This PR improves EnvyControl’s robustness around GPU mode detection and hybrid-mode transitions by adjusting when the Nvidia PCI BusID cache is written, hardening AMD iGPU name detection, and loosening integrated-mode detection to handle partially-present config artifacts.
Changes:
- Return
Nonefromget_amd_igpu_name()whenxrandrexecution fails to avoid a crash path. - Adjust
CachedConfig.adapter()cache creation conditions to avoid unnecessary cache recreation when switching to hybrid. - Update
get_current_mode()to classifyintegratedwhen any integrated-mode marker file exists.
Comments suppressed due to low confidence (1)
envycontrol.py:658
use_cacheis computed beforecreate_cache_file()runs. If the cache file didn’t exist initially, this path will create it but still skipread_cache_file()and won’t rebindget_nvidia_gpu_pci_bus, so later calls during the same run may still hit livelspciand fail if the GPU becomes hidden. Consider recomputinguse_cacheafter cache creation, or directly settinguse_cache = True/ rebinding aftercreate_cache_file()succeeds.
use_cache = os.path.exists(CACHE_FILE_PATH)
# Only cache the GPU PCI bus when leaving hybrid mode.
# Switching *to* hybrid never needs the cached value and the GPU
# may not be visible via lspci if old udev removal rules are still
# in place, which would make create_cache_file() exit early.
if self.is_hybrid() and self.app_args.switch != 'hybrid':
self.create_cache_file()
if use_cache:
self.read_cache_file() # might not be in hybrid mode
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| # Switching *to* hybrid never needs the cached value and the GPU | ||
| # may not be visible via lspci if old udev removal rules are still | ||
| # in place, which would make create_cache_file() exit early. | ||
| if self.is_hybrid() and self.app_args.switch != 'hybrid': |
There was a problem hiding this comment.
if self.is_hybrid() and self.app_args.switch != 'hybrid': will also run when --reset / --reset-sddm are used (since app_args.switch is None), causing an unnecessary cache (re)creation and potential failure on systems where the dGPU isn’t visible even though get_current_mode() reports hybrid. If the intent is “only when leaving hybrid mode”, it would be safer to gate on an explicit switch target (e.g., only when switch is 'integrated' or 'nvidia').
| if self.is_hybrid() and self.app_args.switch != 'hybrid': | |
| if self.is_hybrid() and self.app_args.switch in ('integrated', 'nvidia'): |
This pull request makes several improvements to the GPU detection and mode switching logic in
envycontrol.py, focusing on more robust handling of cache creation, error handling, and mode detection. The changes ensure better reliability when switching GPU modes, especially in hybrid configurations.Improvements to GPU mode switching and cache management:
adaptermethod so that the cache is only recreated when leaving hybrid mode, preventing unnecessary cache updates and handling cases where the GPU may not be visible due to old udev rules.Error handling and robustness:
return Nonestatement inget_amd_igpu_name()if thexrandrcommand fails, ensuring the function exits gracefully on error.Mode detection logic:
get_current_mode()to consider the system to be in 'integrated' mode if any of the relevant files exist (using logical ORs), instead of requiring bothBLACKLIST_PATHand one of the udev rules to exist, making the detection logic more accurate and flexible.