Ticket Created
over 3 years ago

WERETECH-12052

Conflict/race between makeWebRequest and Storage.setValue called from onUpdate on a watchface.

Hi, I was able to reproduce the following problem (both in simulator and in a Descent MK1 using SDK 3.2.5 and 4.0.6):

If the function setValue is called from onUpdate while makeWebRequest is still waiting for the webserver to return data,

the callback function is "lost" (and not called).

The following code reproduce the problem 100% of the time.



using Toybox.Application;
using Toybox.Background;
using Toybox.System;
using Toybox.WatchUi;
using Toybox.Time;
using Toybox.Communications;
using Toybox.Application.Storage;

(:background)
class PiServiceDelegate extends Toybox.System.ServiceDelegate {
  function initialize() {
    System.ServiceDelegate.initialize();
  }
  function onTemporalEvent() {
    // That URI takes about 3 seconds to answer
    var uri = "https://wb.elaine.fi/pi_slow";
    System.println("Before query");
    var options = {
      :methods => Communications.HTTP_REQUEST_METHOD_GET,
      :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
    };
    Communications.makeWebRequest(uri, null, options,
                                  method(:pi_received));
  }
  function pi_received(code, data) {
    System.println(code);
    System.println(data);
    if (code == 200) {
      Background.exit(data);
    }
  }
}

(:background)
class PiWatch extends Application.AppBase {
  public function initialize() {
    AppBase.initialize();
  }
  function onBackgroundData(data) {
    System.println("onBackgroundData: " + data);
  }
  function getServiceDelegate() {
    return [new PiServiceDelegate()];
  }
  function getInitialView() {
    Background.registerForTemporalEvent(new Time.Duration(5 * 60));
    return [new PiWatchView(), new PiWatchDelegate()];
  }
}

class PiWatchView extends WatchUi.WatchFace {
  public function initialize() {
    WatchFace.initialize();
  }
  public function onUpdate(dc) {
    System.println("onUpdate");
    // On simulator, onUpdate is ran every seconds
    // So we will call Storage.setValue between the http request
    // and the result
    // On watch same problem exists
    Storage.setValue("foo", "bar");
    // Note that problem does not exists if Storage.setValue
    // is called in onPartialUpdate
  }
}

class PiWatchDelegate extends WatchUi.WatchFaceDelegate {
  public function initialize() {
    WatchFaceDelegate.initialize();
  }
}


Here is the output:


onUpdate
onUpdate
onUpdate
Background: Before query
onUpdate
onUpdate
onUpdate
Error: Symbol Not Found Error
Details: Failed invoking <symbol>
Stack:
onUpdate
onUpdate
onUpdate



If I comment the setValue line, I get the expected result:

onUpdate
onUpdate
onUpdate
onUpdate
Background: Before query
onUpdate
onUpdate
onUpdate
Background: 200
Background: {pi=>3.140000}
onBackgroundData: {pi=>3.140000}
onUpdate
onUpdate
onUpdate
  • no, no  on simulator look like

    - app start at 12:20:00

    - in view.onshow() - no BAG

    -- saving data to storage for BAG not checking if BAG running

    -- calling  registerForTemporalEvent

    - 12:20:01 onBackgroundData is called ok, immediately because no BAG

    - 12:20:05 run again app from eclipse ctrl+f11 (I don't know if it's similar on device  to quit from WF to widget and return)

    - in view.onshow() - no BAG

    -- saving data to storage for BAG not checking if BAG running

    -- calling  registerForTemporalEvent

    - waiting for onBackgroundData no response  immediately  probably because simulator remember that previous BAG was at 12:20:01, 5 minutes...

    - again run app

    - in view.onshow() - BAG is running

    -- saving data and error

  • if you're doing it in onStart (maybe I don't understand what you said), that runs in the background service

    You can only save anything in the background on devices with newer FW, or there is an exception.. 
    "

  • no, no, I don't save anything in background

    - BAG it's running and waiting for temporary event

    - user quit app

    - user enter the app again

    - in foreground I try start BAG always (so saving for it data) because there is no sure that previous BAG process call onBackgroundData where I clear information about running BAG

    and for f6p there is no problem but for fr735 and mk1 and probably vivactive 3 (error from ERA) I have exactly the same error

    Error: Symbol Not Found Error
    Details: Failed invoking <symbol>
    Stack:
  • onStart runs for the main app as well as a background service, and on older devices, you can not save something to the object store from a background service. It's your bug.

  • I've found the same error in my WF on fr735 (and maybe on vivoactive 3) - on start I don't check if BAG is running and trying save data to storage.