sr_dev_clear(): Always free sdi->priv (devc).

Until now, clear_helper() callbacks for std_dev_clear_with_callback()
were expected to g_free(devc), but not all of them did that.

Have std_dev_clear_with_callback() unconditionally g_free(sdi->priv)
(i.e., devc), regardless of whether a clear_helper() callback was
provided or not. It was doing g_free(sdi->priv) when no callback
was provided already anyway.

This makes the individual drivers' clear_helper() implementations
shorter and prevents errors such as missing g_free(devc) calls.

This works, because all drivers either call std_dev_clear_with_callback()
directly, or indirectly via std_dev_clear().

This also allows us to remove some no-longer needed dev_clear()
and clear_helper() implementations that only did g_free(devc)
in favor of std_dev_clear().
This commit is contained in:
Uwe Hermann 2017-07-11 22:59:52 +02:00
parent 53279f13e4
commit 8bf18daabb
14 changed files with 12 additions and 54 deletions

View File

@ -193,7 +193,6 @@ static void clear_helper(void *priv)
while (g_hash_table_iter_next(&iter, NULL, &value))
g_free(value);
g_hash_table_unref(devc->ch_ag);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -283,19 +283,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
return std_scan_complete(di, devices);
}
static void clear_helper(void *priv)
{
struct dev_context *devc;
devc = priv;
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)
{
return std_dev_clear_with_callback(di, clear_helper);
}
static int dev_open(struct sr_dev_inst *sdi)
{
struct sr_dev_driver *di = sdi->driver;
@ -637,7 +624,7 @@ static struct sr_dev_driver dreamsourcelab_dslogic_driver_info = {
.cleanup = std_cleanup,
.scan = scan,
.dev_list = std_dev_list,
.dev_clear = dev_clear,
.dev_clear = std_dev_clear,
.config_get = config_get,
.config_set = config_set,
.config_list = config_list,

View File

@ -246,7 +246,6 @@ static void clear_helper(void *priv)
devc = priv;
g_free(devc->data_buf);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -351,7 +351,6 @@ static void clear_helper(void *priv)
devc = priv;
g_slist_free(devc->enabled_analog_channels);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -120,8 +120,6 @@ static void clear_helper(void *priv)
g_free(devc->analog_groups);
g_free(devc->digital_groups);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -162,7 +162,6 @@ static void clear_helper(void *priv)
devc = priv;
g_slist_free(devc->enabled_channels);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -160,7 +160,6 @@ static void clear_helper(void *priv)
libusb_free_transfer(devc->xfer_in);
libusb_free_transfer(devc->xfer_out);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -52,7 +52,6 @@ static void clear_helper(void *priv)
ftdi_free(devc->ftdic);
g_free(devc->compressed_buf);
g_free(devc->sample_buf);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -124,8 +124,6 @@ static void clear_helper(void *priv)
lecroy_xstream_state_free(devc->model_state);
g_free(devc->analog_groups);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -288,7 +288,6 @@ static void clear_helper(void *priv)
g_free(devc->trigger_source);
g_free(devc->trigger_slope);
g_free(devc->analog_groups);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -295,7 +295,6 @@ static void clear_helper(void *priv)
devc = priv;
g_free(devc->channels);
g_free(devc->channel_groups);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -203,25 +203,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
return std_scan_complete(di, devices);
}
static void clear_helper(void *priv)
{
struct dev_context *devc;
devc = priv;
if (devc->acquisition) {
sr_err("Cannot clear device context during acquisition!");
return; /* Leak and pray. */
}
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)
{
return std_dev_clear_with_callback(di, clear_helper);
}
/* Drain any pending data from the USB transfer buffers on the device.
* This may be necessary e.g. after a crash or generally to clean up after
* an abnormal condition.
@ -750,7 +731,7 @@ static struct sr_dev_driver sysclk_lwla_driver_info = {
.cleanup = std_cleanup,
.scan = scan,
.dev_list = std_dev_list,
.dev_clear = dev_clear,
.dev_clear = std_dev_clear,
.config_get = config_get,
.config_set = config_set,
.config_channel_set = config_channel_set,

View File

@ -131,7 +131,6 @@ static void clear_helper(void *priv)
g_free(devc->analog_groups);
g_free(devc->digital_groups);
g_free(devc);
}
static int dev_clear(const struct sr_dev_driver *di)

View File

@ -333,16 +333,18 @@ SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi)
* This function can be used to implement the dev_clear() driver API
* callback. dev_close() is called before every sr_dev_inst is cleared.
*
* The only limitation is driver-specific device contexts (sdi->priv).
* The only limitation is driver-specific device contexts (sdi->priv / devc).
* These are freed, but any dynamic allocation within structs stored
* there cannot be freed.
*
* @param[in] driver The driver which will have its instances released.
* Must not be NULL.
* @param[in] clear_private If not NULL, this points to a function called
* with sdi->priv as argument. The function can then clear
* with sdi->priv (devc) as argument. The function can then clear
* any device instance-specific resources kept there.
* It must also clear the struct pointed to by sdi->priv.
* It must NOT clear the struct pointed to by sdi->priv (devc),
* since this function will always free it after clear_private()
* has run.
*
* @retval SR_OK Success.
* @retval SR_ERR_ARG Invalid argument.
@ -388,12 +390,13 @@ SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver,
if (sdi->inst_type == SR_INST_MODBUS)
sr_modbus_free(sdi->conn);
}
/* Clear driver-specific stuff, if any. */
if (clear_private)
/* The helper function is responsible for freeing
* its own sdi->priv! */
clear_private(sdi->priv);
else
g_free(sdi->priv);
/* Clear sdi->priv (devc). */
g_free(sdi->priv);
sr_dev_inst_free(sdi);
}