CallLater / App.Quit not always working

  1. 6 weeks ago

    Arthur v

    Apr 16 Testers Netherlands
    Edited 6 weeks ago

    I'm working with 2019r3.1 and a compiled web service (no UI) on Linux (64-bit). Here's the code:

    If shutdownRequest Then
      MessageAdd(CurrentMethodName + ": shutting down in 20 seconds.")
      // Breathing room for script completion & possible upload new exe
      Xojo.Core.Timer.CallLater(20000, AddressOf QuitApp)
    End If

    The above is triggered in a timer (main thread) and works fine. Here's the QuitApp method:

    MessageAdd(CurrentMethodName)
    App.Quit()

    This concept works most of the time, but not when the shutdownRequest is set after what appears to be a hanging thread because of an open HTTP socket.

    What happens in that case is the "shutting down in 20 seconds" is being logged infinitely (timer works fine) but the QuitApp method is never logged / called.

    Could it be that the hanging thread blocks CallLater somehow? Can I check that or is there a workaround?

  2. Greg O

    Apr 16 Xojo Inc scout.galaxy.barn

    Make sure your thread yields once in a while or those timers won’t fire. See Thread.Sleep.

  3. Arthur v

    Apr 16 Testers Netherlands

    The main App.Open only starts a bunch of timers like this one and finishes, so I don't think I can yield anything. Right?

    Also, the timer itself runs fine and, ehhh, on time and every time (logging each 5 second interval). So how could the CallLater not find time to fire?

    (How many times can you use 'time' in a post...)

  4. Ulrich B

    Apr 16 Testers, Xojo Pro Europe (Germany, Berlin) · xo...

    In what context do the timers run when the main app has quit?

  5. Arthur v

    Apr 16 Testers Netherlands
    Edited 6 weeks ago

    I'm sorry, but I don't really know how to answer that question. The App didn't quit, App.Open finishes after having done a bunch of stuff, including:

    MessageAdd("Starting shutdown timer.")
    timerShutdown = New Timer
    AddHandler timerShutdown.Action, AddressOf timerShutdownAction
    timerShutdown.Period = 5000 // Every 5 seconds
    timerShutdown.Mode = Timer.ModeMultiple

    The code for the timer is in the first post. When the flag {App.shutdownRequest} has been set, it calls the App.Method.

    This always works, except in the scenario I described earlier.

    In both cases {timerShutdown} happily keeps on firing every 5 seconds, but the {QuitApp} is not called if there's a hanging (not properly cleaned up - destructor didn't run) thread / HTTPSocket (HTTP error?) in another part of the App. Therefore I was wondering if this somehow can mess up CallLater.

    As a workaround I've added an extra counter in the timer that wil directly call the method after a couple of cycles. It's not easy to test though as this scenario almost never happens...

  6. James D

    Apr 17 Testers, Xojo Pro Europe (Switzerland)

    You should probably stop accepting connections before going into your close down routine.

  7. Arthur v

    Apr 17 Testers Netherlands

    All connections are closed at that point in time. Except for the one that has not destructed correctly.

    Still, why should it block the CallLater mechanism?

  8. James D

    Apr 17 Testers, Xojo Pro Europe (Switzerland)

    @Arthur v;den Boogaart All connections are closed at that point in time. Except for the one that has not destructed correctly.

    Still, why should it block the CallLater mechanism?

    I don't see anything in your code setting this property to False:

    https://docs.xojo.com/WebApplication.AcceptingConnections

  9. Arthur v

    Apr 17 Testers Netherlands
    Edited 6 weeks ago

    Correct. Should that help or even matter? Does that influence CallLater?

    My app is a web service which does not get incoming connections other then pages received from outgoing REST calls.

    Also, this code works 99% of the time. It's only a problem after the scenario I described earlier.

    It's not that the main thread(s) are busy since everything has been shut down too. The app has plenty of time, which is also witnessed by the precision of the timer going off. Even with every thread running full blast this mechanism works fine as I have sleeps all over the place...

  10. Arthur v

    Apr 17 Testers Netherlands

    @James D I don't see anything in your code setting this property to False:

    https://docs.xojo.com/WebApplication.AcceptingConnections

    I'm wondering how this works though...

    Allows you to Start/Stop a web app's ability to accept connections. Setting this property to False will stop the server(s) and disconnect all active sockets immediately.

    So does it stop accepting new ones and kill all outstanding REST (HTTPSocket) calls? So all threads waiting for a HTTP reply are going to be disrupted?

    If that's the case I won't use it until after these threads have been gracefully exited...

  11. Kevin G

    Apr 17 Xojo Pro Gatesheed, England

    If by web service you mean a console app / service application maybe you could use a different approach.

    Your main thread will have some kind of loop which keeps the process running.

    Rather than your shutdown using CallLater to trigger a method to execute app.Quit, why don't you use a boolean property which indicates if the loop should continue. Your shutdown detection code would flip the property value which would exit the loop and end the process.

  12. Arthur v

    Apr 17 Testers Netherlands

    I appreciate the input, but how would this help me? Right now the app works fine and it's heavily multi-threaded so I don't see how or why I would have to change this. Not sure it would be a better design to begin with, but I'm open for good arguments!

  13. Kevin G

    Apr 17 Xojo Pro Gatesheed, England

    @Arthur v;den Boogaart I appreciate the input, but how would this help me? Right now the app works fine and it's heavily multi-threaded so I don't see how or why I would have to change this. Not sure it would be a better design to begin with, but I'm open for good arguments!

    My approach would mean that you don't need to use CallLater which according to your diagnoses. doesn't appear to be working correctly.

  14. Arthur v

    Apr 17 Testers Netherlands
    Edited 6 weeks ago

    True. But I thought (a loop with only) a sleep for the main thread (in App.Open) was considered to be 'not done'...

    https://forum.xojo.com/34110-sleeping-the-main-thread/p1#p278712

  15. Kevin G

    Apr 17 Xojo Pro Gatesheed, England

    @Arthur v;den Boogaart True. But I thought (a loop with only) a sleep for the main thread (in App.Open) was considered to be 'not done'...

    Oh, it looks like you are doing this using a Desktop project.
    Is there any reason why you aren't using a Console project since your app doesn't have a GUI?

  16. Arthur v

    Apr 17 Testers Netherlands
    Edited 6 weeks ago

    No sorry, it is a console web app...

  17. Kevin G

    Apr 17 Xojo Pro Gatesheed, England

    @Arthur v;den Boogaart No sorry, it is a console web app...

    Sorry, never touched a web app before.

  18. Julian S

    Apr 17 Xojo Pro UK

    Can you replicate this in a small project that you can upload here for us to look over? If you need to block a connection fir the test just try to connect to a random port on localhost.

  19. James D

    Apr 17 Testers, Xojo Pro Europe (Switzerland)
    Edited 6 weeks ago

    @Arthur v;den Boogaart So does it stop accepting new ones and kill all outstanding REST (HTTPSocket) calls? So all threads waiting for a HTTP reply are going to be disrupted?

    Yes it cleanly closed down everything and in my experience it is necessary for a correct clean up.

    @Arthur v;den Boogaart If that's the case I won't use it until after these threads have been gracefully exited...

    But then you need to track the threads and make sure they are correctly closed down, that than giving it a random 20 seconds and hoping for the best.

  20. 5 weeks ago

    Arthur v

    Apr 20 Testers Netherlands

    Thanks for the replies guys! Somehow I didn't get an email from the forum.

    @Julian S - A small project... Dunno about that, will take some time as the App is fairly complex with lots of timers starting threads which spin up threads running (e.g.) XojoScripts in other threads. I'm pretty sure that's related to the issue.

    @James D - I already track the threads because I need to know if they're finished. That gets double checked when the CallLater fires after 20 seconds. *If* it fires.

    For now I'll settle for extra counter I've put in. Also I'm going in to see if I can find a way to catch and destruct the hanging thread (reference?) somehow.

    Just for the record: CallLater is not completely clean though. Maybe it gets queued (?) after (blocked by) the hanging thread or something? No clue how this stuff works internally.

  21. Newer ›

or Sign Up to reply!