Shared Library Changes for Release 2.2.7
Shared library libddcutil is backwardly compatible with the ones in ddcutil 2.2.1 and later. The SONAME is unchanged as libddcutil.so.5. The released library file is libddcutil.so.5.5.1.
Permission denied errors on /dev/i2c devices
Calling open() on a /dev/i2c device for which the user has RW permission sometimes (rarely) fails with Linux error EACCES. It tends to happen immediately after a return from sleep. This elusive problem has most frequently been reported by KDE PowerDevil users, on Framework computers and Arch based distributions.
The cause, apparently, is a race condition: the tiny window of time between when a /dev/i2c device becomes visible and time that permissions granted by udev rules using the uaccess token are applied.
libddcutil attempts to solve this problem by pausing before certain operations and after a return from sleep is detected. It also retries open() operations that fail with error EACCES if it appears that the failure may have been caused by the race condition.
Retries and delays are a trade-off: operations that initially fail may in fact eventually succeed, but retrying makes ddcutil slower with no benefit for operations that don't. The optimal settings are not obvious. The following options (which can be put in configuration file ddcutilrc) have been added to tune behaviour.
- ~~pause-after-resume-ms The number of milliseconds libddcutil may pause after dbus reports a resume from sleep. The default is 500 ms.
- -max-eacces_retry-ms Limits the number of milliseconds for retrying open() calls on /dev/i2c devices when it appears likely, having checked the ACL, that the open() call will eventually succeed. The default is 3000 ms.
- --enable/disable-early-permission-checks Perform basic permission checks
before performing operations that might generate a flurry of EACCES errors.
The drawback of this option is that the basic permission might be performed too soon, generating permission failures that might otherwise resolve by the time the open() calls are actually needed. The default is enable.
Alternatively, tor those encountering the problem, the simpler solution may be to grant permission to the /dev/i2c devices by assigning users to group i2c.
Other Changes
- Implemented a basic segfault handler. It writes the traced function stack of the current thread to the system log, then invokes the prior handler.
- Added a thread that watches for dbus PrepareForSleep messages, in order to calculate the time since the most recent return from sleep. If opening a /dev/i2c device fails with errno EACCES shortly after returning from sleep, the open is retried.
- Re-enable reporting of laptop display connection/disconnection.
- Segfault in function diagnose_open_failure_to_syslog(). Issue #596
- ddca_redetect_displays(): Recover from an unexpected system state that previously triggered assert() failures. Diagnostics are written to the system log. If display watch is not running on entry to the function, it is not restarted at the end. Addresses issue #595, (powerdevil crashes with assertion failure in libddcutil after resume from sleep/hibernate) and KDE bug 517571 (KDE Power Management Crash in DDCutilPrivateSingleton::redetect after letting laptop sleep).
- In dw_create_display_status_event(), the test for event type DDCA_EVENT_DDC_DISABLED incorrectly used flag DDCA_DISPLAY_EVENT_DDC_WORKING.