Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/mobile/exp/sensor: can't reenable sensors once disabled on Android #12501

Closed
rakyll opened this issue Sep 4, 2015 · 5 comments
Closed

x/mobile/exp/sensor: can't reenable sensors once disabled on Android #12501

rakyll opened this issue Sep 4, 2015 · 5 comments

Comments

@rakyll
Copy link
Contributor

rakyll commented Sep 4, 2015

The proxying goroutine will block on readSignal forever if all sensors are disabled on Android. Once every sensor is disabled, there is no way for other signals to be consumed by the same proxying goroutine.

@rakyll rakyll self-assigned this Sep 4, 2015
@rakyll rakyll added this to the Unreleased milestone Sep 4, 2015
@rakyll
Copy link
Contributor Author

rakyll commented Oct 5, 2015

I would like to reuse the the existing app looper to enable, disable and read the sensor events.

The app looper is not suffering from the indefinitely blocked case because there will be new app lifecycle events during the lifetime of an app. Reusing it sounds like a better strategy than trying to invent a preemption strategy for the sensor looper.

@crawshaw, any thoughts?

@rakyll
Copy link
Contributor Author

rakyll commented Oct 6, 2015

Given it a second thought, trying to wake the blocked pollAll with ALooper_wake or destroying the underlying ALooper if no sensors enabled sound like a better option than coupling the sensor package with app's ALooper.

@gopherbot
Copy link

CL https://golang.org/cl/15438 mentions this issue.

@crawshaw
Copy link
Member

crawshaw commented Oct 6, 2015

I would prefer minimizing the number of OS-specific hooks the app package needs to export, so if this can be done inside the sensor package that would be best.

@rakyll
Copy link
Contributor Author

rakyll commented Oct 7, 2015

Rather than going for one of the complex proposals above, I decided to introduce a hard poll timeout which allowed the thread not to be blocked indefinitely and gave the poller a fair execution time.

@golang golang locked and limited conversation to collaborators Oct 9, 2016
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 10, 2021
The sensor package had a deadlock case if it started to poll the
events but all sensors have been disabled on the underlying ALooper.

Consider the following program:

  app.Main(func(a app.App) {
    sensor.Enable(a, sensor.Gyroscope, time.Millisecond)
    go func() {
      time.Sleep(5 * time.Second)
      sensor.Disable(sensor.Gyroscope)
      time.Sleep(2 * time.Second)
      sensor.Enable(a, sensor.Gyroscope, time.Millisecond)
    }()
    for e := range a.Events() {
    case sensor.Event:
      //...
    }

The initial Enable will enable the gyroscope and start polling events
from the ALooper. After 5 seconds, the gyroscope will be disabled.

  ALooper_pollAll(-1, NULL, &events, NULL)

will block indefinately because there are no events will be
available until another sensor is enabled.

After 2 seconds, we will attempt to enable the gyroscope again. But,
the underlying thread will be blocked at pollAll and won't be able
to make the sensor enabling call on the same thread.

In order to overcome this deadlock case, this thread introduces a
hard timeout limit during polling. If timeout occurs, the looper
thread will be unblocked and select{} statement will be able to
handle {enable,disable,close}Signal cases.

Fixes golang/go#12501.

Change-Id: I35efa2e29057ca37f8ac0f38be8dc59c9b8262b3
Reviewed-on: https://go-review.googlesource.com/15438
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 11, 2021
The sensor package had a deadlock case if it started to poll the
events but all sensors have been disabled on the underlying ALooper.

Consider the following program:

  app.Main(func(a app.App) {
    sensor.Enable(a, sensor.Gyroscope, time.Millisecond)
    go func() {
      time.Sleep(5 * time.Second)
      sensor.Disable(sensor.Gyroscope)
      time.Sleep(2 * time.Second)
      sensor.Enable(a, sensor.Gyroscope, time.Millisecond)
    }()
    for e := range a.Events() {
    case sensor.Event:
      //...
    }

The initial Enable will enable the gyroscope and start polling events
from the ALooper. After 5 seconds, the gyroscope will be disabled.

  ALooper_pollAll(-1, NULL, &events, NULL)

will block indefinately because there are no events will be
available until another sensor is enabled.

After 2 seconds, we will attempt to enable the gyroscope again. But,
the underlying thread will be blocked at pollAll and won't be able
to make the sensor enabling call on the same thread.

In order to overcome this deadlock case, this thread introduces a
hard timeout limit during polling. If timeout occurs, the looper
thread will be unblocked and select{} statement will be able to
handle {enable,disable,close}Signal cases.

Fixes golang/go#12501.

Change-Id: I35efa2e29057ca37f8ac0f38be8dc59c9b8262b3
Reviewed-on: https://go-review.googlesource.com/15438
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
@rsc rsc unassigned rakyll Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants