Building42 / Telegraph

Secure Web Server for iOS, tvOS and macOS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Http connections closes after a while

cflorion opened this issue · comments

Hi :)
The library is great, everything works well thanks !
But, after a while (i.e 10 minutes) leaving the server on (an iPad) with a socket connection open (by calling server.start(onPort:), the other devices cannot connect the server anymore.

If I restart the server (stop then start), the connection comes back. II tried putting a timer that restarts the server periodically but this is not a perfect solution since after some tests some client requests fail when they happen at the wrong moment during the restart (even if I call server.stop(immediately: false) )

Is it something that you are aware of ? Is there a best practice I did not get ?

Thanks a lot :)

Hi!

Thank you! Glad you like it!

Does the app stay active in the foreground? If your app is suspended Apple will eventually unload your app and close the connections.

See https://github.com/Building42/Telegraph#what-if-the-device-goes-on-standby

Have you tried keeping the demo app active for 10 minutes?
Do you encounter the same problem there?

The app stays in the foreground and the device doesn't lock automatically.
What do you mean by keeping the app active ? I should have actions on the app and not let it alone ?

Does that mean thatif the socket connection does not have work to do it closes after a while ? Should I have a timer that ping the connection so it stays alive ?

Hi

I wanted to see how this IOS Example app will behave with respect to handling HTTP connections. It works great while it's in foreground. But I wanted an end behavior, where after launching this Example IOS App, I would like to have another third party IOS app on the device (that will HTTP-talk to this IOS Example App). But as soon as switch (iOS example App is not running anymore in the foreground - as expected):

All http connections from the third party app to 'now' background IOS Example App fails.

Please note: I had configured the IOS Example app to 'Background App Refresh' in capabilities when I built it and enabled BackgroundRefresh on the device for this app.

Can you please advise how I can make this app to keep accepting (as I switch to other apps) the connections until I close the app (either manually or programmatically) in the background/daemon fashion?

Can you please give any indication that by doing the below (as per the readme), will get me what I want?

UIApplication.beginBackgroundTask

Thank you

Sorry for my late reply, I've been crazy busy.

@cflorion
Using Telegraph in our project I haven't noticed the server becoming unresponsive. Could there perhaps be something blocking the requests? Is your app multi-threaded? If you have some code that I can use to reproduce the problem, I'd be happy to take a look at what might go wrong.

Also are you using the latest version of Telegraph?

@rahulsu When the app gets suspended you can ask iOS for a bit more time before it is unloaded from memory. You do so by starting a background task when the app is suspended. Please note that this is a different mechanism then the Background Refresh requests of URLSession.

In my experience you'll never get more than 3 minutes.

You can add the following code to your AppDelegate:

private var backgroundTask: UIBackgroundTaskIdentifier = .invalid

/// Raised when the app is suspended.
func applicationDidEnterBackground(_ application: UIApplication) {
  print("Application did enter background")

  backgroundTask = UIApplication.shared.beginBackgroundTask {
    print("Background task expired")

    // This is the last possible moment to execute code.
    // Apple might unload your app from memory at this point.
  }

  let timeRemaining = UIApplication.shared.backgroundTimeRemaining
  print("Background task started, we have \(timeRemaining) sec. remaining")
}

/// Raised when the app is resumed.
func applicationWillEnterForeground(_ application: UIApplication) {
  print("Application will enter background")

  cancelBackgroundTask()
}

/// Cancels an active background task.
func cancelBackgroundTask() {
  guard backgroundTask != .invalid else { return }

  print("Cancelling background task")

  UIApplication.shared.endBackgroundTask(backgroundTask)
  backgroundTask = .invalid
}

In my experience backgroundTimeRemaining isn't reliable, it sometimes has some weird values. The closure of the beginBackgroundTask is a good spot to stop the HTTP server and gracefully end any running requests.

Unfortunately I don't think there is a way to keep the HTTP server running in the background past the 3 minute mark. Apple wants to make sure that the foreground app always has all the resources it requires and will remove your app from memory if it has to. Any open connections will be closed.

@Zyphrax Thanks for your answer !
I am still trying to identify and better understand my own problem.
When you are asking if my app is multithreaded, what do you mean ?
My local server is initialized from the main thread, so I guess the routes callbacks are called on the main thread also ?

server = CRHTTPServer()
server!.put("/lock") { [weak self] (request, response, next) in
  self?.handleLock(request: request, response: response, next: next)
}

Should I dispatch handleLock() on another thread ?
Should I also call server = CRHTTPServer()on another thread ?

Thanks a lot

@cflorion The code you provided seems to be using Criollo instead of Telegraph. I'm not familiar with Criollo and unfortunately can't tell you how they handle requests.

Like most webservers Telegraph handles requests in a background thread, this allows simultaneous requests and prevents blocking the main thread. You do have to be careful and make sure that the code in the route callbacks is thread-safe. If for example two requests occur at the same time and try to change a single variable you could run into a race condition.

Yes, sorry @Zyphrax I copied code from another project... 🤦‍♂️

@cflorion No problem. If you do run into issues with Telegraph please let me know, I'd be happy to take a look at it!