[PATCH 2/2] port-probe: simplify task completion
Aleksander Morgado
aleksander at aleksander.es
Fri Mar 11 14:04:24 UTC 2016
On Thu, Mar 10, 2016 at 9:10 AM, Aleksander Morgado
<aleksander at aleksander.es> wrote:
> We no longer need to complete in idle, because the limitation imposed by the
> serial port methods no longer exists.
> ---
This has been merged to git master now.
> src/mm-port-probe.c | 230 ++++++++++++++++++----------------------------------
> 1 file changed, 81 insertions(+), 149 deletions(-)
>
> diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
> index e260f34..c09b8a1 100644
> --- a/src/mm-port-probe.c
> +++ b/src/mm-port-probe.c
> @@ -323,9 +323,6 @@ typedef struct {
> /* ---- MBIM probing specific context ---- */
> MMPortMbim *mbim_port;
> #endif
> -
> - /* Error reporting during idle completion */
> - GError *possible_error;
> } PortProbeRunContext;
>
> static gboolean serial_probe_at (MMPortProbe *self);
> @@ -333,11 +330,8 @@ static gboolean serial_probe_qcdm (MMPortProbe *self);
> static void serial_probe_schedule (MMPortProbe *self);
>
> static void
> -port_probe_run_context_cleanup (PortProbeRunContext *ctx)
> +port_probe_run_context_free (PortProbeRunContext *ctx)
> {
> - /* We cleanup signal connections here, to be executed before a task is
> - * completed (and when it's freed) */
> -
> if (ctx->cancellable && ctx->at_probing_cancellable_linked) {
> g_cancellable_disconnect (ctx->cancellable, ctx->at_probing_cancellable_linked);
> ctx->at_probing_cancellable_linked = 0;
> @@ -352,13 +346,6 @@ port_probe_run_context_cleanup (PortProbeRunContext *ctx)
> g_signal_handler_disconnect (ctx->serial, ctx->buffer_full_id);
> ctx->buffer_full_id = 0;
> }
> -}
> -
> -static void
> -port_probe_run_context_free (PortProbeRunContext *ctx)
> -{
> - /* Cleanup signals */
> - port_probe_run_context_cleanup (ctx);
>
> if (ctx->serial) {
> if (mm_port_serial_is_open (ctx->serial))
> @@ -387,85 +374,9 @@ port_probe_run_context_free (PortProbeRunContext *ctx)
> if (ctx->cancellable)
> g_object_unref (ctx->cancellable);
>
> - /* We may have an error here if the task was completed
> - * with error and was cancelled at the same time */
> - if (ctx->possible_error)
> - g_error_free (ctx->possible_error);
> -
> g_slice_free (PortProbeRunContext, ctx);
> }
>
> -static gboolean
> -task_return_in_idle_cb (GTask *task)
> -{
> - PortProbeRunContext *ctx;
> -
> - ctx = g_task_get_task_data (task);
> -
> - if (g_task_return_error_if_cancelled (task))
> - goto out;
> -
> - if (ctx->possible_error) {
> - g_task_return_error (task, ctx->possible_error);
> - ctx->possible_error = NULL;
> - goto out;
> - }
> -
> - g_task_return_boolean (task, TRUE);
> -
> -out:
> - g_object_unref (task);
> - return G_SOURCE_REMOVE;
> -}
> -
> -static void
> -task_return_in_idle (MMPortProbe *self,
> - GError *error)
> -{
> - PortProbeRunContext *ctx;
> - GTask *task;
> -
> - /* Steal task from private info */
> - g_assert (self->priv->task);
> - task = self->priv->task;
> - self->priv->task = NULL;
> -
> - /* Early cleanup of signals */
> - ctx = g_task_get_task_data (task);
> - port_probe_run_context_cleanup (ctx);
> -
> - /* We will propatate an error if we have one */
> - ctx->possible_error = error;
> -
> - /* Schedule idle to complete.
> - *
> - * NOTE!!!!!!!
> - *
> - * Completing not-on-idle is very problematic due to how we process
> - * responses in the serial port: the response returned by the finish()
> - * call is constant, so that completion is always not-on-idle. And if we
> - * mix both tasks completed not-on-idle, we may end up reaching a point
> - * where the serial port is being closed while the serial port response
> - * is still being processed.
> - *
> - * By always completing this task on-idle, we make sure that the serial
> - * port gets closed always once the response processor has been finished.
> - */
> - g_idle_add ((GSourceFunc) task_return_in_idle_cb, task);
> -}
> -
> -static gboolean
> -task_return_error_in_idle_if_cancelled (MMPortProbe *self)
> -{
> - if (!g_cancellable_is_cancelled (g_task_get_cancellable (self->priv->task)))
> - return FALSE;
> -
> - /* We complete without error because the error is set afterwards by
> - * the GTask in g_task_return_error_if_cancelled() */
> - task_return_in_idle (self, NULL);
> - return TRUE;
> -}
> -
> /***************************************************************/
> /* QMI & MBIM */
>
> @@ -616,8 +527,10 @@ wdm_probe (MMPortProbe *self)
> ctx->source_id = 0;
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> + }
>
> /* QMI probing needed? */
> if ((ctx->flags & MM_PORT_PROBE_QMI) &&
> @@ -634,7 +547,8 @@ wdm_probe (MMPortProbe *self)
> }
>
> /* All done now */
> - task_return_in_idle (self, NULL);
> + g_task_return_boolean (self->priv->task, TRUE);
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
>
> @@ -657,8 +571,10 @@ serial_probe_qcdm_parse_response (MMPortSerialQcdm *port,
> ctx = g_task_get_task_data (self->priv->task);
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return;
> + }
>
> response = mm_port_serial_qcdm_command_finish (port, res, &error);
> if (!error) {
> @@ -726,8 +642,10 @@ serial_probe_qcdm (MMPortProbe *self)
> ctx->source_id = 0;
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> + }
>
> mm_dbg ("(%s/%s) probing QCDM...",
> g_udev_device_get_subsystem (self->priv->port),
> @@ -747,25 +665,27 @@ serial_probe_qcdm (MMPortProbe *self)
> /* Open the QCDM port */
> ctx->serial = MM_PORT_SERIAL (mm_port_serial_qcdm_new (g_udev_device_get_name (self->priv->port)));
> if (!ctx->serial) {
> - task_return_in_idle (self,
> - g_error_new (MM_CORE_ERROR,
> - MM_CORE_ERROR_FAILED,
> - "(%s/%s) Couldn't create QCDM port",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port)));
> + g_task_return_new_error (self->priv->task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "(%s/%s) Couldn't create QCDM port",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port));
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
>
> /* Try to open the port */
> if (!mm_port_serial_open (ctx->serial, &error)) {
> - task_return_in_idle (self,
> - g_error_new (MM_SERIAL_ERROR,
> - MM_SERIAL_ERROR_OPEN_FAILED,
> - "(%s/%s) Failed to open QCDM port: %s",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port),
> - (error ? error->message : "unknown error")));
> + g_task_return_new_error (self->priv->task,
> + MM_SERIAL_ERROR,
> + MM_SERIAL_ERROR_OPEN_FAILED,
> + "(%s/%s) Failed to open QCDM port: %s",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port),
> + (error ? error->message : "unknown error"));
> g_clear_error (&error);
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
>
> @@ -779,12 +699,13 @@ serial_probe_qcdm (MMPortProbe *self)
> len = qcdm_cmd_version_info_new ((char *) (verinfo->data + 1), 9);
> if (len <= 0) {
> g_byte_array_unref (verinfo);
> - task_return_in_idle (self,
> - g_error_new (MM_SERIAL_ERROR,
> - MM_SERIAL_ERROR_OPEN_FAILED,
> - "(%s/%s) Failed to create QCDM versin info command",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port)));
> + g_task_return_new_error (self->priv->task,
> + MM_SERIAL_ERROR,
> + MM_SERIAL_ERROR_OPEN_FAILED,
> + "(%s/%s) Failed to create QCDM versin info command",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port));
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
> verinfo->len = len + 1;
> @@ -936,8 +857,10 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
> ctx = g_task_get_task_data (self->priv->task);
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return;
> + }
>
> /* If AT probing cancelled, end this partial probing */
> if (g_cancellable_is_cancelled (ctx->at_probing_cancellable)) {
> @@ -959,13 +882,14 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
> &result_error)) {
> /* Were we told to abort the whole probing? */
> if (result_error) {
> - task_return_in_idle (self,
> - g_error_new (MM_CORE_ERROR,
> - MM_CORE_ERROR_UNSUPPORTED,
> - "(%s/%s) error while probing AT features: %s",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port),
> - result_error->message));
> + g_task_return_new_error (self->priv->task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_UNSUPPORTED,
> + "(%s/%s) error while probing AT features: %s",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port),
> + result_error->message);
> + g_clear_object (&self->priv->task);
> goto out;
> }
>
> @@ -1016,7 +940,7 @@ serial_probe_at (MMPortProbe *self)
> ctx->source_id = 0;
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self)) {
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
> @@ -1083,7 +1007,8 @@ at_custom_init_ready (MMPortProbe *self,
>
> if (!ctx->at_custom_init_finish (self, res, &error)) {
> /* All errors propagated up end up forcing an UNSUPPORTED result */
> - task_return_in_idle (self, error);
> + g_task_return_error (self->priv->task, error);
> + g_clear_object (&self->priv->task);
> return;
> }
>
> @@ -1103,8 +1028,10 @@ serial_probe_schedule (MMPortProbe *self)
> ctx = g_task_get_task_data (self->priv->task);
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return;
> + }
>
> /* If we got some custom initialization setup requested, go on with it
> * first. */
> @@ -1172,8 +1099,9 @@ serial_probe_schedule (MMPortProbe *self)
> return;
> }
>
> - /* All done! Finish asynchronously */
> - task_return_in_idle (self, NULL);
> + /* All done! */
> + g_task_return_boolean (self->priv->task, TRUE);
> + g_clear_object (&self->priv->task);
> }
>
> static void
> @@ -1237,8 +1165,10 @@ serial_open_at (MMPortProbe *self)
> ctx->source_id = 0;
>
> /* If already cancelled, do nothing else */
> - if (task_return_error_in_idle_if_cancelled (self))
> + if (g_task_return_error_if_cancelled (self->priv->task)) {
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> + }
>
> /* Create AT serial port if not done before */
> if (!ctx->serial) {
> @@ -1250,12 +1180,13 @@ serial_open_at (MMPortProbe *self)
>
> ctx->serial = MM_PORT_SERIAL (mm_port_serial_at_new (g_udev_device_get_name (self->priv->port), subsys));
> if (!ctx->serial) {
> - task_return_in_idle (self,
> - g_error_new (MM_CORE_ERROR,
> - MM_CORE_ERROR_FAILED,
> - "(%s/%s) couldn't create AT port",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port)));
> + g_task_return_new_error (self->priv->task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "(%s/%s) couldn't create AT port",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port));
> + g_clear_object (&self->priv->task);
> return G_SOURCE_REMOVE;
> }
>
> @@ -1281,12 +1212,13 @@ serial_open_at (MMPortProbe *self)
> /* Abort if maximum number of open tries reached */
> if (++ctx->at_open_tries > 4) {
> /* took too long to open the port; give up */
> - task_return_in_idle (self,
> - g_error_new (MM_CORE_ERROR,
> - MM_CORE_ERROR_FAILED,
> - "(%s/%s) failed to open port after 4 tries",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port)));
> + g_task_return_new_error (self->priv->task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "(%s/%s) failed to open port after 4 tries",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port));
> + g_clear_object (&self->priv->task);
> g_clear_error (&error);
> return G_SOURCE_REMOVE;
> }
> @@ -1298,14 +1230,14 @@ serial_open_at (MMPortProbe *self)
> return G_SOURCE_REMOVE;
> }
>
> - port_probe_run_context_cleanup (ctx);
> - task_return_in_idle (self,
> - g_error_new (MM_SERIAL_ERROR,
> - MM_SERIAL_ERROR_OPEN_FAILED,
> - "(%s/%s) failed to open port: %s",
> - g_udev_device_get_subsystem (self->priv->port),
> - g_udev_device_get_name (self->priv->port),
> - (error ? error->message : "unknown error")));
> + g_task_return_new_error (self->priv->task,
> + MM_SERIAL_ERROR,
> + MM_SERIAL_ERROR_OPEN_FAILED,
> + "(%s/%s) failed to open port: %s",
> + g_udev_device_get_subsystem (self->priv->port),
> + g_udev_device_get_name (self->priv->port),
> + (error ? error->message : "unknown error"));
> + g_clear_object (&self->priv->task);
> g_clear_error (&error);
> return G_SOURCE_REMOVE;
> }
> @@ -1411,8 +1343,8 @@ mm_port_probe_run (MMPortProbe *self,
> mm_dbg ("(%s/%s) port probing finished: no more probings needed",
> g_udev_device_get_subsystem (self->priv->port),
> g_udev_device_get_name (self->priv->port));
> - port_probe_run_context_cleanup (ctx);
> - task_return_in_idle (self, NULL);
> + g_task_return_boolean (self->priv->task, TRUE);
> + g_clear_object (&self->priv->task);
> return;
> }
>
> --
> 2.7.1
>
--
Aleksander
https://aleksander.es
More information about the ModemManager-devel
mailing list