Closed scubachristopher closed 3 years ago
hey @scubachristopher thanks for your feedback
gzReadSourceByte hasn't changed much since that time you hinted at retrying after a fail, it still returns 0 if the read was successful or -1 after a second try failed.
However thanks to you I've found a way to replicate the error (turning off the wifi during transfer) so I'll be able to make a few tests and hopefully come back soon with a solution.
[edit] Spoil : https://github.com/tobozo/ESP32-targz/blob/master/src/uzlib/tinflate.c#L203
[edit2] Possible fix on this temporary branch
I turned off the WiFi in the middle of the transfer:
23:49:21.323 -> Connected as
23:49:21.323 -> 192.168.1.19
23:49:22.217 -> [TAR] firmware_example_esp32.spiffs.bin 1507328 bytes - 1507328 Total bytes
23:49:22.217 -> Progress: 0% βββββββββββββββββββββββββ 25% ββββββ[W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 2 - AUTH_EXPIRE
23:49:29.543 -> [E][ssl_client.cpp:33] _handle_error(): [data_to_read():270]: (-76) UNKNOWN ERROR CODE (004C)
23:49:31.465 -> [E][ESP32-targz-lib.cpp:1015] gzReadSourceByte(): readSourceByte read error, available is 0. failed at retry
23:49:31.465 -> uzlib_get_byte/readSourceByte Errors: 1
23:49:31.498 -> [E][ESP32-targz-lib.cpp:1767] tarGzStreamUpdater(): tarGzStreamExpander returned error code -6
23:49:31.498 -> [E][ESP32-targz-lib.cpp:108] targz_system_halt(): System halted after error code #-6
big thanks for fueling this library with your quality feedback, this is now fixed in the latest release, closing this as solved, feel free to reopen if necessary
@scubachristopher I recently had retry failures when streaming from a SPI ethernet library.
In that situation, retrying right after the failure didn't work because the input buffer was still being filled by another task.
I came up with something different based on a timeout value, it gives more solid results in stressful situations, will publish a new release soon :-)
// consume and return a byte from the source stream into the argument 'out'.
// returns 0 on success, or -1 on error.
unsigned int GzUnpacker::gzReadSourceByte(CC_UNUSED struct GZ::TINF_DATA *data, unsigned char *out)
{
_start: // using goto to avoid repeated code blocks
if (tarGzIO.gz->readBytes( out, 1 ) != 1) {
uint32_t now = millis();
uint32_t timeout = now + targz_read_timeout;
while( !tarGzIO.gz->available() ) {
if( millis()>timeout ) {
log_e("gz stream still unresponsive after %dms timeout, giving up", targz_read_timeout);
return -1;
}
vTaskDelay(1); // let the app breathe
}
log_w("gz stream was unresponsive during %dms (timeout=%dms)", millis()-now, targz_read_timeout);
goto _start;
} else {
//log_v("read 1 byte: 0x%02x", out[0] );
}
if( tarGzIO.gz_size > 0 ) {
stream_bytesleft -= 1;
}
return 0;
}
Heya,
Thought we were good but I didn't test a failure case. Seems when the retry fails, although you return -1, you never bail back to the caller.
Caller snippet:
Never gets to GZUnpacker with the following log output:
So I modified GzUnpacker::gzReadSourceByte to just return -1 and got this:
My expectation (fair to say perhaps anyone's) is that it would return false.
Of course when it succeeds, it's beautiful.
I can revert back to my cloned repo with the retry before your refactor. Prefer to stay current. Let me know your thoughts...