Liveupdate strange behavior

Thank you. Created ticket: https://github.com/defold/defold/issues/5499

3 Likes

We now have a PR for this issue, and when itā€™s done, weā€™ll merge it into the 1.2.179 beta for you to test (today or tomorrow)

1 Like

The 1.2.179 BETA is now updated with a fix for the #5499 issue

3 Likes

Thank you very much!
We have checked - it works.
Weā€™ll keep our fingers crossed for further improvements. :slight_smile:

2 Likes

Hello everyone!
Leeeeetā€™s delve into another problem with LiveUpdate. :slight_smile:

The situation is as follows:

  1. we are doing an apk with a LiveUpdate.
  2. everything used to work.
  3. but at some point the problems started.
  4. the files of the LiveUpdate are downloading badly (see below).

We get mistakes like this:

ERROR:SCRIPT: HTTP request to 'https://battlehive.fra1.cdn.digitaloceanspaces.com/liveupdate/debug/android/02f2b6b25fa9c71be00b791bdbdbe5f6e1075dd3' failed (http result: -1  socket result: 0)
WARNING:DLIB: Unhandled ssl status code: 0 ( 0000)                                                                                                                                                 
ERROR:SCRIPT: HTTP request to 'https://battlehive.fra1.cdn.digitaloceanspaces.com/liveupdate/debug/android/5cadeca8fbc4831e13b724e3a0c88f077b0b9294' failed (http result: -1  socket result: -1000)

Apart from that, it is very common for a message like this to drop:

INFO:DLIB: Flushing http cache to disk

What the hell is that?

And in the end we get this outcome:

ERROR:RESOURCE: Byte mismatch in decrypted manifest signature. Different keys used for signing?                     
ERROR:LIVEUPDATE: Verification failure for Liveupdate archive for resource: 02f2b6b25fa9c71be00b791bdbdbe5f6e1075dd3

BUT! We have already downloaded this file, and successfully!
Yes, the first time it didnā€™t want to download (see above) but our system re-runs the download in such situations.

What do you think about this?

The ā€œFlushing http cache to diskā€ comes from storing the latest http request info (such as the ETag and max age).

The cache is written to disc every 5 seconds (if itā€™s dirty):

We have already downloaded this file, and successfully!

Is this the manifest file?
If so, are the ETag and the expiration changed? What is the return HTTP code?

Still, it seems strange that the manifest signature would differ if itā€™s the same file :thinking:

As for the https request failing, Iā€™m not really sure whatā€™s causing it. Iā€™m not even sure the socket code ā€œ0ā€ is an error code, which is also curious.
What if you print out the headers in this case, what info (e.g. status code) do they return?

2 Likes

Do you know when and what caused it? An update of Defold? Some change to the server hosting the files?

No. Nothing supernatural was going on. It was the first thing we thought of, so we carefully checked exactly what we were changing.

No, itā€™s just the biggest file in the LiveUpdate - itā€™s 12 mb. There is only one such file.

D defold  : DEBUG:SCRIPT: URL_NEW:	http://46.216.55.60:8000/debug/android/liveupdate.game.dmanifest
E defold  : ERROR:SCRIPT: HTTP request to 'http://46.216.55.60:8000/debug/android/liveupdate.game.dmanifest' failed (http result: -1  socket result: 0)
W defold  : WARNING:DLIB: Profiler Message.Dispatch @__http_worker_2 took 10.008 seconds
D defold  : DEBUG:SCRIPT: 
D defold  : { --[[0x7c0d02e570]]
D defold  :   status = 0,
D defold  :   response = "
D defold  : Ā©Š“A
D defold  : &ā€ ŠŖĀ­Ń› (2
D defold  : _Ā»+~јŠ¤JњŠ²Ń„Ń“.gJā€¦@њ[Aі
D defold  : ā€žā€ .Š§ā€¹ŃŠŠž"RŠµ;Š¢=Š¦ā€”?
D defold  : ŠŖ9ŠˆŠ¾^kK
D defold  : ?/main/windows/player_new_level/player_new_level_generated_0.gocŠ½ā€œŠøŠ³ŃœŅŃš
D defold  : Ā»|",
D defold  :   headers = { --[[0x7c0d02e600]]
D defold  :     server = "SimpleHTTP/0.6 Python/3.8.5",
D defold  :     content-type = "application/octet-stream",
D defold  :     content-length = "1073730",
D defold  :     last-modified = "Thu, 18 Mar 2021 14:21:04 GMT",
D defold  :     date = "Thu, 18 Mar 2021 14:32:11 GMT"
D defold  :   }
D defold  : }
D defold  : DEBUG:SCRIPT: unloaded:	hash: [loading]	->  loaded:	hash: [error]
1 Like

We have a theory.

In the project settings (game.project) there is an item ā€œhttp_timeoutā€. The feeling is that this value has an effect even in situations where the timeout is set explicitly.

Next, the file that can not download properly (or can not be saved via resource.store_resource) is the largest file in the entire archive - 12 mb.
However, this is not the case for all users. But it is common enough to be a nuisance.

The funny part of the problem is that this file is downloaded in 4 seconds from the browser, but cannot be downloaded via http.request() from the project.

Perhaps the problem is in the implementation of http.request()?

Cannot be downloaded? How? Do you get an error?

Are you using the new way of directly downloading to file instead of to memory?

local options = {
    path = "some/path"
}
http.request(..., options)

PS Not sure if itā€™s only the path you need to provide or path and filenameā€¦ @JCash knows.

@britzl we donā€™t yet have a way to store a single resource directly from disc.

Also ā€œpathā€ to me suggests directory+ filename name. And yes, you specify the path where the file is to be saved.

The network.http_timeoutis used as the default value. If you specify a timeout, it will be used instead.

Next, the file that can not download properly (or can not be saved via resource.store_resource) is the largest file in the entire archive - 12 mb.

I donā€™t think our code having any size constraints per se, however, it is an interesting attribute that might be a clue to whatā€™s going on.

The funny part of the problem is that this file is downloaded in 4 seconds from the browser, but cannot be downloaded via http.request() from the project.
Perhaps the problem is in the implementation of http.request()?

Itā€™s hard to tell without investigating some more.
Perhaps you can provide me with that url so I can make some tests towards it too?

As for the suggestion @britzl gave, itā€™s not (yet) useful for storing live update files one by one. Itā€™s used when downloading the entire .zip file at once. We should look into that very soon though, as itā€™s faster/leaner than passing all that data via Lua.

Sorry for confusing things! But a good option for the future.

https://battlehive.fra1.cdn.digitaloceanspaces.com/liveupdate/debug/android/02f2b6b25fa9c71be00b791bdbdbe5f6e1075dd3

1 Like

I canā€™t reproduce the failed http.request() locally.
Even tried with a network limiter set to 20mbps, and the download takes ~20 seconds.

I wonder if it could be that if bad data is stored in the http cache, the next time we ask for that data, weā€™ll get bad data back.
Then when we want to store it in live resources, it will produce the manifest signature error. Perhaps if you calculate and print a checksum for that file, to compare

You mention your ā€œsystem re-runs the download in such situations.ā€, do you set the ā€œignore_cacheā€ in that case?
If not, it might retrieve the file again from the cache (if itā€™s in the cache), so it might be a good thing to try. (not as a permanent solution, but to help try pinpoint the issue)

EDIT: I do get the ā€œ/url/ failed (http result: -1 socket result: 0)ā€ if I set it to timeout.
I donā€™t get the ā€œUnhandled ssl status codeā€ though.

1 Like

@morgerion After looking further into the http requests, I found some issues, and indeed they were related to timeout issues. I have PRā€™s ready for @britzl and they should be in the next release.

  1. The per-request timeout value wasnā€™t always used #5669

  2. Donā€™t reuse socket connection after the previous request (using the same connection) timed out. (Fixes the ā€œUnhandled ssl status code: 0 ( 0000)ā€ in this case) #5671

4 Likes

Oh, thatā€™s interesting.

In general, our problem is roughly this:

  1. when using wi-fi it is very rare that a 12 mb file cannot be downloaded.
  2. when using a mobile network this file canā€™t be downloaded often.
  3. in all these cases using a foreign download method (e.g. via a browser) works fine.

I get the impression that http.request() is working strangely.
Suppose a timeout is to blame. But why does the browser download this file in 4 seconds, but http.request() cannot download in 30 seconds?

Iā€™m not sure. during these tests I never got a download time above .6 seconds for that 12mb file (on my Wifi) using Defold.

I just tested using my cell network which is at 15mbit currently, and that worked fine too. Downloading the file in Defold took 5.1s and using wget it tool 7.2s.

Currently I have no real clue as to why in your case it doesnā€™t download faster.

Both fixes are now building on the alpha branch, and Iā€™ll let you know when you can test that to see if the behavior is still the same.

Edit: The build is now available on https://d.defold.com/alpha/

1 Like

And one more question regarding http.request() behaviour.
If we use up to 32 simultaneous calls to http.request(), the LiveUpdate takes on average a minute to download.
But if we use 4 simultaneous calls to http.request(), the download time averages 4 minutes.

Why? What is the optimal number of simultaneous http.requests()?

1 Like

I need to do some tests and read a bit of code to give you a definitive answer. One thing I know itā€™s that the http_service.cpp uses a thread per http_client.cpp instance. The default thread count is 4 but can be configured through the game project setting network.http_thread_count. Iā€™m not entirely sure what happens when more requests are made than the number of threads. I need to investigate this.

1 Like