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:
parent
53279f13e4
commit
8bf18daabb
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
17
src/std.c
17
src/std.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue