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
Parents
  • I had and have a lot problems with storage and have an impression that system sometimes unload functions (especially when near memory limit).

    Try to use  if(Toybox.Application has :Storage) to check if error is exactly in this place and if you have storage already.

    System behave strange if you use on start saving data or run background etc. so I've decided to avoid it and run "dangerous" code after full initialise.

    And saving something every second is not good idea, but I'm saving to storage in loop :) but not the same key and first saving null then value and not in onUpdata of course but in onBackgroundData.

    And take 4.0.7 because something can be fixed.

    I've ran my WF on mk1 sim and no problem with webReq and saving to storage in loop Slight smile

Comment
  • I had and have a lot problems with storage and have an impression that system sometimes unload functions (especially when near memory limit).

    Try to use  if(Toybox.Application has :Storage) to check if error is exactly in this place and if you have storage already.

    System behave strange if you use on start saving data or run background etc. so I've decided to avoid it and run "dangerous" code after full initialise.

    And saving something every second is not good idea, but I'm saving to storage in loop :) but not the same key and first saving null then value and not in onUpdata of course but in onBackgroundData.

    And take 4.0.7 because something can be fixed.

    I've ran my WF on mk1 sim and no problem with webReq and saving to storage in loop Slight smile

Children
No Data