Open Bug 1359403 Opened 8 years ago Updated 3 months ago

Web Extension alarms delayed if computer has been suspended after creation of alarm

Categories

(WebExtensions :: General, defect, P5)

54 Branch
defect

Tracking

(Not tracked)

UNCONFIRMED

People

(Reporter: w0t.w0t.owl, Unassigned)

References

(Depends on 1 open bug)

Details

(Whiteboard: [alarms][triaged])

Attachments

(1 file)

2.84 KB, application/x-xpinstall
Details
Attached file Bugzilla Alarm.xpi
User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0 Build ID: 20170418123315 Steps to reproduce: 1. Create a Web Extension to schedule an alarm for 2 minutes later using the "when" parameter of browser.alarms.create (see attached sample). 2. Load the Web Extension as temporary add-on. 3. Put computer to sleep once add-on has been loaded. Keep computer in suspension for approx 30 seconds. 4. Wake computer up, and wait for scheduled alarm to fire. 5. Compare alarm scheduled time and actual alarm firing time. Actual results: Alarm fires more than 2 minutes after it was scheduled. Expected results: Alarm should fire exactly 2 minutes after it was scheduled.
This problem is also reproducible on User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0 Build ID: 20170413074756 This is my first time filing a bug here, any guidance is much appreciated.
Component: Activity Streams: General → WebExtensions: Untriaged
Product: Firefox → Toolkit
Priority: -- → P5
Whiteboard: [alarms][triaged]
I dug into this a little today, and it looks like while macOS and Windows listen for power management/suspend events, the GTK implementation doesn't. I'm guessing it's due to the lack of consensus on how to listen for these events across Linux + init implementations, BSD, etc. If one wanted to listen for these events on Linux using systemd, it seems that inhibitor locks might be of use: https://www.freedesktop.org/wiki/Software/systemd/inhibit/ If one wanted to avoid coupling tightly to systemd, but didn't mind staying coupled to Linux, there's the CLOCK_BOOTTIME clock (as opposed to the currently used CLOCK_MONOTONIC in mozglue/misc/TimeStamp_posix.cpp), which apparently is the same as CLOCK_MONOTONIC only it handles system suspends properly. A cursory look at the FreeBSD documentation leads me to believe that CLOCK_UPTIME is the BSD equivalent, at least on FreeBSD. The timer facility is used all over Firefox, so I might be a bit hesistant to make such a change to such a widely used component, but it *does* seem functionality equivalent to listening for sleep/wakeup events and recalculating timers then.
I dug in a little more - it turns that Firefox seems to function normally when I switch to CLOCK_BOOTTIME (after adding it to the seccomp filter), but I don't think that'll work after all, since the timer thread uses condition variables to sleep, and the underlying implementation (using pthread_cond_timedwait) can't use CLOCK_BOOTTIME. As far as inhibitor locks go, it appears one can't use to listen for wake events, which is kind of the important part when recalculating timers post-wake. There might be other APIs that allow one to sleep using CLOCK_BOOTTIME (clock_nanosleep seems to work), or other APIs for subscribing to ACPI power state events, but maybe on Linux/BSD the timer system should just wake up once a minute or something and see if the wall clock has drifted considerably in comparison to the monotonic clock.
Rob, thanks for doing that research. I don't think this is a WebExtensions bug directly, and bug 1204823 appears to be related. Its not clear to me whether a fix for that bug would bubble all the way up to fixing this one or not. But that bug stalled a while back based on a need to support old Linux kernels. If you're interested, you could check in over there to see if it can get unblocked now that some time has elapsed...
Depends on: 1204823
Thanks for pointing me in the right direction, Andrew! I don't know how much I can help with such a pervasive issue, but I'll take a look!
Product: Toolkit → WebExtensions
Component: Untriaged → General

A similar problem also affects Thunderbird, just replace "Web Extension alarms" with "mail checks".
The cause is the same - CLOCK_MONOTONIC is used internally for timers and time stamps in general.

As Rob has said in comment 3 while it is easy to make mozilla::TimeStamp family return CLOCK_BOOTTIME
there is a problem with pthreads condition variables that threads use for sleeping -
they don't support the CLOCK_BOOTTIME clock.
In fact, the problem lies deeper than pthreads library - the kernel futex() syscall only supports
CLOCK_MONOTONIC and CLOCK_REALTIME clocks.

I can see basically two solutions here:

  1. Add CLOCK_BOOTTIME support to the kernel futex() syscall THEN use it to implement CLOCK_BOOTTIME
    support for pthreads condition variables in glibc THEN switch mozilla::detail::ConditionVariableImpl
    and mozilla::TimeStamp to this clock, OR:

  2. Rewrite mozilla::detail::ConditionVariableImpl and so using timerfds for Linux -
    this will use about 2 extra fds per condition variable.
    A serious error handling needs to be added to these classes in this case since the current implementation
    just throws an assertion failure on any error.

This problem isn't limited to Mozilla software - pretty much everywhere CLOCK_MONOTONIC is currently used
the CLOCK_BOOTTIME behaviour is really expected.
That's why a year ago kernel people tried to rename CLOCK_MONOTONIC to CLOCK_MONOTONIC_ACTIVE while
aliasing CLOCK_MONOTONIC to CLOCK_BOOTTIME.
However, they had to back out of that change since it broke some (non-Mozilla) software.

I was directed to this thread after observing the same behavior on MacOS. Since it looks like the general consensus points to this being a Linux-only issue, I figured my observations may be of use. I tested on both MacOS and Windows, and found that the issue is only present on MacOS.

MacOS User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:68.0) Gecko/20100101 Firefox/68.0
Windows User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0

Here's a gist of my findings:
https://gist.github.com/dbuer/6946615935dc0799dbeea1071f067db7

Severity: normal → S3

The topic of alarm handling when the host system sleeps has come up in the WebExtensions Community Group in https://github.com/w3c/webextensions/issues/433.

Progress on that issue stalled due to a combination of two factors: within the group we were aligning on using wall clock time for alrms, but we also wanted to align with web behavior, which is currently not well defined. See also https://github.com/whatwg/html/issues/6759.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: