hameg-hmo: Avoid getting stuck upon SCPI timeouts.
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. This fixes bug #1323.
This commit is contained in:
parent
d779dcacb7
commit
bb0665868e
|
@ -961,6 +961,7 @@ SR_PRIV int sr_scpi_get_block(struct sr_scpi_dev_inst *scpi,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
GString* response;
|
GString* response;
|
||||||
|
gsize oldlen;
|
||||||
char buf[10];
|
char buf[10];
|
||||||
long llen;
|
long llen;
|
||||||
long datalen;
|
long datalen;
|
||||||
|
@ -990,14 +991,14 @@ SR_PRIV int sr_scpi_get_block(struct sr_scpi_dev_inst *scpi,
|
||||||
*scpi_response = NULL;
|
*scpi_response = NULL;
|
||||||
|
|
||||||
/* Get (the first chunk of) the response. */
|
/* Get (the first chunk of) the response. */
|
||||||
while (response->len < 2) {
|
do {
|
||||||
ret = scpi_read_response(scpi, response, timeout);
|
ret = scpi_read_response(scpi, response, timeout);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
g_mutex_unlock(&scpi->scpi_mutex);
|
g_mutex_unlock(&scpi->scpi_mutex);
|
||||||
g_string_free(response, TRUE);
|
g_string_free(response, TRUE);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
} while (response->len < 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SCPI protocol data blocks are preceeded with a length spec.
|
* SCPI protocol data blocks are preceeded with a length spec.
|
||||||
|
@ -1044,25 +1045,33 @@ SR_PRIV int sr_scpi_get_block(struct sr_scpi_dev_inst *scpi,
|
||||||
g_string_erase(response, 0, 2 + llen);
|
g_string_erase(response, 0, 2 + llen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the initially assumed length does not cover the data block
|
* Re-allocate the buffer size to the now known length
|
||||||
* length, then re-allocate the buffer size to the now known
|
* and keep reading more chunks of response data.
|
||||||
* length, and keep reading more chunks of response data.
|
|
||||||
*/
|
*/
|
||||||
if (response->len < (unsigned long)(datalen)) {
|
oldlen = response->len;
|
||||||
int oldlen = response->len;
|
g_string_set_size(response, datalen);
|
||||||
g_string_set_size(response, datalen);
|
g_string_set_size(response, oldlen);
|
||||||
g_string_set_size(response, oldlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (response->len < (unsigned long)(datalen)) {
|
if (oldlen < (unsigned long)(datalen)) {
|
||||||
ret = scpi_read_response(scpi, response, timeout);
|
do {
|
||||||
if (ret < 0) {
|
oldlen = response->len;
|
||||||
g_mutex_unlock(&scpi->scpi_mutex);
|
ret = scpi_read_response(scpi, response, timeout);
|
||||||
g_string_free(response, TRUE);
|
|
||||||
return ret;
|
/* On timeout truncate the buffer and send the partial response
|
||||||
}
|
* instead of getting stuck on timeouts...
|
||||||
if (ret > 0)
|
*/
|
||||||
timeout = g_get_monotonic_time() + scpi->read_timeout_us;
|
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);
|
g_mutex_unlock(&scpi->scpi_mutex);
|
||||||
|
|
Loading…
Reference in New Issue