Correctly set the length of the buffer used to hold the SCPI response from the device containing the binary acquisition data.
If a timeout occurs, truncate the buffer and send the partial response from the device instead of getting stuck on timeouts ! Thanks to Stefan Brüns for reviewing the first version of this patch and spotting out a serious problem with it. Signed-off-by: Guido Trentalancia <gu...@trentalancia.com> --- src/scpi/scpi.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff -pru libsigrok-git-20102018-orig/src/scpi/scpi.c libsigrok-git-20102018-fix-scpi-response-buffer-length/src/scpi/scpi.c --- libsigrok-git-20102018-orig/src/scpi/scpi.c 2018-10-20 13:12:30.983966965 +0200 +++ libsigrok-git-20102018-fix-scpi-response-buffer-length/src/scpi/scpi.c 2018-10-29 22:53:10.419718436 +0100 @@ -945,6 +945,7 @@ SR_PRIV int sr_scpi_get_block(struct sr_ { int ret; GString* response; + gsize oldlen; char buf[10]; long llen; long datalen; @@ -974,14 +975,14 @@ SR_PRIV int sr_scpi_get_block(struct sr_ *scpi_response = NULL; /* Get (the first chunk of) the response. */ - while (response->len < 2) { + do { ret = scpi_read_response(scpi, response, timeout); if (ret < 0) { g_mutex_unlock(&scpi->scpi_mutex); g_string_free(response, TRUE); return ret; } - } + } while (response->len < 2); /* * SCPI protocol data blocks are preceeded with a length spec. @@ -1028,25 +1029,33 @@ SR_PRIV int sr_scpi_get_block(struct sr_ g_string_erase(response, 0, 2 + llen); /* - * If the initially assumed length does not cover the data block - * length, then re-allocate the buffer size to the now known - * length, and keep reading more chunks of response data. + * Re-allocate the buffer size to the now known length + * and keep reading more chunks of response data. */ - if (response->len < (unsigned long)(datalen)) { - int oldlen = response->len; - g_string_set_size(response, datalen); - g_string_set_size(response, oldlen); - } - - while (response->len < (unsigned long)(datalen)) { - ret = scpi_read_response(scpi, response, timeout); - if (ret < 0) { - g_mutex_unlock(&scpi->scpi_mutex); - g_string_free(response, TRUE); - return ret; - } - if (ret > 0) - timeout = g_get_monotonic_time() + scpi->read_timeout_us; + oldlen = response->len; + g_string_set_size(response, datalen); + g_string_set_size(response, oldlen); + + if (oldlen < (unsigned long)(datalen)) { + do { + oldlen = response->len; + ret = scpi_read_response(scpi, response, timeout); + + /* On timeout truncate the buffer and send the partial response + * instead of getting stuck on timeouts... + */ + if (ret == SR_ERR_TIMEOUT) { + datalen = oldlen; + break; + } + if (ret < 0) { + g_mutex_unlock(&scpi->scpi_mutex); + g_string_free(response, TRUE); + return ret; + } + if (ret > 0) + timeout = g_get_monotonic_time() + scpi->read_timeout_us; + } while (response->len < (unsigned long)(datalen)); } g_mutex_unlock(&scpi->scpi_mutex); _______________________________________________ sigrok-devel mailing list sigrok-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sigrok-devel