diff options
author | Guido Günther <agx@sigxcpu.org> | 2014-03-01 10:17:13 +0100 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-03-01 10:23:31 +0100 |
commit | a76ea3fbda245337ddd85c7f92cb8fdf0917835b (patch) | |
tree | f85169e89f5a2bd0ad351eee3495a81df8a9006b /src | |
parent | 8447b03c0a53c44b4051eb223a76c2d5fd24ea67 (diff) |
Unbreak gzip decompression on larger query results
g_converter_convert doesn't guarantee to convert all data
when we set G_CONVERTER_INPUT_AT_END so make sure we continue
to process the data. Fixes errors like
** (process:4072): WARNING **: Unhandled condition 1
Traceback (most recent call last):
File "examples/trip-query.py", line 47, in trips_cb
raise Exception("Failed to find any trips")
Exception: Failed to find any trips
Error: timed out
Thanks: Matthias Schmitz for the report
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/de-db.c | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/src/providers/de-db.c b/src/providers/de-db.c index d58aba2..6857eb4 100644 --- a/src/providers/de-db.c +++ b/src/providers/de-db.c @@ -538,7 +538,7 @@ decompress (const gchar *in, gsize inlen, gsize read, written; GConverter *decomp = NULL; GConverterResult conv; - gsize outbuflen = inlen * 2; + gsize outbuflen, buflen, outpos = 0, inpos = 0; gchar *outbuf = NULL; g_return_val_if_fail (inlen > 0, ret); @@ -546,43 +546,49 @@ decompress (const gchar *in, gsize inlen, g_return_val_if_fail (err, ret); decomp = (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); - while (TRUE) { - g_free (outbuf); - outbuf = g_try_malloc (outbuflen); - if (outbuf == NULL) - break; + + outbuflen = buflen = inlen * 2; + outbuf = g_try_malloc (outbuflen); + if (outbuf == NULL) + goto out; + + do { conv = g_converter_convert (decomp, - in, inlen, - outbuf, outbuflen, + (in + inpos), inlen, + (outbuf + outpos), buflen, G_CONVERTER_INPUT_AT_END, &read, &written, err); - if (conv == G_CONVERTER_ERROR) { - if ((*err)->code == G_IO_ERROR_NO_SPACE) { - outbuflen *= 2; - g_clear_error (err); - continue; - } else { - break; - } - } else if (conv == G_CONVERTER_FINISHED) { - if (read != inlen) { - g_warning ("Expected %" G_GSIZE_FORMAT - ", got %" G_GSIZE_FORMAT, inlen, read); - break; - } + + switch (conv) { + case G_CONVERTER_ERROR: + goto out; + case G_CONVERTER_FINISHED: + outpos += written; ret = 0; + goto out; + case G_CONVERTER_CONVERTED: + outpos += written; + inpos += read; + inlen -= read; + if (outbuflen - written < buflen) { + outbuflen += buflen; + outbuf = g_try_realloc (outbuf, outbuflen); + if (outbuf == NULL) + goto out; + } break; - } else { + case G_CONVERTER_FLUSHED: + default: g_warning ("Unhandled condition %d", conv); - ret = -1; - break; + goto out; } - } + } while (TRUE); +out: if (ret == 0) { *out = outbuf; - *outlen = written; + *outlen = outpos; } else g_free (outbuf); |