Drop the Big GDK Lock

GDK has a lock to mark critical sections inside the backends.
Additionally, code that would re-enter into the GTK main loop was
supposed to hold the lock.

Back in the Good Old Days™ this was guaranteed to kind of work only on
the X11 backend, and would cause a neat explosion on any other GDK
backend.

During GTK+ 3.x we deprecated the API to enter and leave the critical
sections, and now we can remove all the internal uses of the lock, since
external API that uses GTK+ 4.x won't be able to hold the GDK lock.

https://bugzilla.gnome.org/show_bug.cgi?id=793124
This commit is contained in:
Emmanuele Bassi 2018-02-02 16:34:40 +01:00
parent c655759cef
commit 888dfe499d
25 changed files with 19 additions and 210 deletions

View File

@ -60,14 +60,10 @@ gdk_event_source_prepare (GSource *source,
GdkDisplay *display = ((GdkEventSource*) source)->display;
gboolean retval;
gdk_threads_enter ();
*timeout = -1;
retval = (_gdk_event_queue_find_first (display) != NULL);
gdk_threads_leave ();
return retval;
}
@ -77,16 +73,12 @@ gdk_event_source_check (GSource *source)
GdkEventSource *event_source = (GdkEventSource*) source;
gboolean retval;
gdk_threads_enter ();
if (event_source->display->event_pause_count > 0 ||
event_source->event_poll_fd.revents & G_IO_IN)
retval = (_gdk_event_queue_find_first (event_source->display) != NULL);
else
retval = FALSE;
gdk_threads_leave ();
return retval;
}
@ -385,8 +377,6 @@ gdk_event_source_dispatch (GSource *source,
GdkDisplay *display = ((GdkEventSource*) source)->display;
GdkEvent *event;
gdk_threads_enter ();
event = gdk_display_get_event (display);
if (event)
@ -396,8 +386,6 @@ gdk_event_source_dispatch (GSource *source,
gdk_event_free (event);
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -708,8 +708,6 @@ gdk_mir_event_source_dispatch (GSource *g_source,
* back here again.
*/
gdk_threads_enter ();
event = gdk_display_get_event (source->display);
if (event)
@ -719,8 +717,6 @@ gdk_mir_event_source_dispatch (GSource *g_source,
gdk_event_free (event);
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -620,8 +620,6 @@ gdk_event_prepare (GSource *source,
{
gboolean retval;
gdk_threads_enter ();
/* The prepare stage is the stage before the main loop starts polling
* and dispatching events. The autorelease poll is drained here for
* the preceding main loop iteration or, in case of the first iteration,
@ -655,8 +653,6 @@ gdk_event_prepare (GSource *source,
retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
_gdk_quartz_event_loop_check_pending ());
gdk_threads_leave ();
return retval;
}
@ -665,16 +661,12 @@ gdk_event_check (GSource *source)
{
gboolean retval;
gdk_threads_enter ();
if (_gdk_display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (_gdk_display) != NULL;
else
retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
_gdk_quartz_event_loop_check_pending ());
gdk_threads_leave ();
return retval;
}
@ -685,8 +677,6 @@ gdk_event_dispatch (GSource *source,
{
GdkEvent *event;
gdk_threads_enter ();
_gdk_quartz_display_queue_events (_gdk_display);
event = _gdk_event_unqueue (_gdk_display);
@ -698,8 +688,6 @@ gdk_event_dispatch (GSource *source,
gdk_event_free (event);
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -1732,9 +1732,7 @@ _gdk_quartz_display_queue_events (GdkDisplay *display)
g_list_free_1 (node);
gdk_event_free (event);
gdk_threads_leave ();
[NSApp sendEvent:nsevent];
gdk_threads_enter ();
}
_gdk_quartz_event_loop_release_event (nsevent);

View File

@ -115,8 +115,6 @@ gdk_event_source_dispatch (GSource *base,
GdkDisplay *display = source->display;
GdkEvent *event;
gdk_threads_enter ();
event = gdk_display_get_event (display);
if (event)
@ -126,8 +124,6 @@ gdk_event_source_dispatch (GSource *base,
g_object_unref (event);
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -3979,8 +3979,6 @@ gdk_event_prepare (GSource *source,
GdkWin32EventSource *event_source = (GdkWin32EventSource *)source;
gboolean retval;
gdk_threads_enter ();
*timeout = -1;
if (event_source->display->event_pause_count > 0)
@ -3990,8 +3988,6 @@ gdk_event_prepare (GSource *source,
(modal_win32_dialog == NULL &&
GetQueueStatus (QS_ALLINPUT) != 0));
gdk_threads_leave ();
return retval;
}
@ -4001,8 +3997,6 @@ gdk_event_check (GSource *source)
GdkWin32EventSource *event_source = (GdkWin32EventSource *)source;
gboolean retval;
gdk_threads_enter ();
if (event_source->display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (event_source->display) != NULL;
else if (event_source->event_poll_fd.revents & G_IO_IN)
@ -4012,8 +4006,6 @@ gdk_event_check (GSource *source)
else
retval = FALSE;
gdk_threads_leave ();
return retval;
}
@ -4025,8 +4017,6 @@ gdk_event_dispatch (GSource *source,
GdkWin32EventSource *event_source = (GdkWin32EventSource *)source;
GdkEvent *event;
gdk_threads_enter ();
_gdk_win32_display_queue_events (event_source->display);
event = _gdk_event_unqueue (event_source->display);
@ -4047,8 +4037,6 @@ gdk_event_dispatch (GSource *source,
}
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -1731,12 +1731,8 @@ process_internal_connection (GIOChannel *gioc,
{
GdkInternalConnection *connection = (GdkInternalConnection *)data;
gdk_threads_enter ();
XProcessInternalConnection ((Display*)connection->display, connection->fd);
gdk_threads_leave ();
return TRUE;
}

View File

@ -409,8 +409,6 @@ gdk_event_source_prepare (GSource *source,
GdkDisplay *display = ((GdkEventSource*) source)->display;
gboolean retval;
gdk_threads_enter ();
*timeout = -1;
if (display->event_pause_count > 0)
@ -419,8 +417,6 @@ gdk_event_source_prepare (GSource *source,
retval = (_gdk_event_queue_find_first (display) != NULL ||
gdk_check_xpending (display));
gdk_threads_leave ();
return retval;
}
@ -430,8 +426,6 @@ gdk_event_source_check (GSource *source)
GdkEventSource *event_source = (GdkEventSource*) source;
gboolean retval;
gdk_threads_enter ();
if (event_source->display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (event_source->display) != NULL;
else if (event_source->event_poll_fd.revents & G_IO_IN)
@ -440,8 +434,6 @@ gdk_event_source_check (GSource *source)
else
retval = FALSE;
gdk_threads_leave ();
return retval;
}
@ -491,8 +483,6 @@ gdk_event_source_dispatch (GSource *source,
GdkDisplay *display = ((GdkEventSource*) source)->display;
GdkEvent *event;
gdk_threads_enter ();
event = gdk_display_get_event (display);
if (event)
@ -502,8 +492,6 @@ gdk_event_source_dispatch (GSource *source,
g_object_unref (event);
}
gdk_threads_leave ();
return TRUE;
}

View File

@ -351,8 +351,6 @@ gtk_application_before_emit (GApplication *g_application,
{
GtkApplication *application = GTK_APPLICATION (g_application);
gdk_threads_enter ();
gtk_application_impl_before_emit (application->priv->impl, platform_data);
}
@ -360,7 +358,6 @@ static void
gtk_application_after_emit (GApplication *application,
GVariant *platform_data)
{
gdk_threads_leave ();
}
static void

View File

@ -201,10 +201,7 @@ bookmarks_file_changed (GFileMonitor *monitor,
case G_FILE_MONITOR_EVENT_DELETED:
g_slist_free_full (manager->bookmarks, _gtk_bookmark_free);
manager->bookmarks = read_bookmarks (file);
gdk_threads_enter ();
notify_changed (manager);
gdk_threads_leave ();
break;
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:

View File

@ -1220,11 +1220,7 @@ gtk_dialog_run (GtkDialog *dialog)
&ri);
ri.loop = g_main_loop_new (NULL, FALSE);
gdk_threads_leave ();
g_main_loop_run (ri.loop);
gdk_threads_enter ();
g_main_loop_unref (ri.loop);
ri.loop = NULL;

View File

@ -4735,15 +4735,12 @@ file_system_model_got_thumbnail (GObject *object,
if (queried == NULL)
return;
gdk_threads_enter ();
/* now we know model is valid */
/* file was deleted */
if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
{
g_object_unref (queried);
gdk_threads_leave ();
return;
}
@ -4757,8 +4754,6 @@ file_system_model_got_thumbnail (GObject *object,
g_object_unref (info);
g_object_unref (queried);
gdk_threads_leave ();
}
static gboolean

View File

@ -103,13 +103,9 @@ volumes_changed (GVolumeMonitor *volume_monitor,
gpointer volume,
gpointer user_data)
{
GtkFileSystem *file_system;
GtkFileSystem *file_system = user_data;
gdk_threads_enter ();
file_system = GTK_FILE_SYSTEM (user_data);
g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
gdk_threads_leave ();
}
static void
@ -413,10 +409,8 @@ query_info_callback (GObject *source_object,
if (async_data->callback)
{
gdk_threads_enter ();
((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
file_info, error, async_data->data);
gdk_threads_leave ();
}
if (file_info)
@ -473,11 +467,9 @@ drive_poll_for_media_cb (GObject *source_object,
g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
async_data = (AsyncFuncData *) user_data;
gdk_threads_enter ();
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
(GtkFileSystemVolume *) source_object,
error, async_data->data);
gdk_threads_leave ();
if (error)
g_error_free (error);
@ -494,11 +486,9 @@ volume_mount_cb (GObject *source_object,
g_volume_mount_finish (G_VOLUME (source_object), result, &error);
async_data = (AsyncFuncData *) user_data;
gdk_threads_enter ();
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
(GtkFileSystemVolume *) source_object,
error, async_data->data);
gdk_threads_leave ();
if (error)
g_error_free (error);
@ -565,10 +555,8 @@ enclosing_volume_mount_cb (GObject *source_object,
if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
g_clear_error (&error);
gdk_threads_enter ();
((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
error, async_data->data);
gdk_threads_leave ();
if (error)
g_error_free (error);

View File

@ -1137,8 +1137,6 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
GList *walk, *files;
GError *error = NULL;
gdk_threads_enter ();
files = g_file_enumerator_next_files_finish (enumerator, res, &error);
if (files)
@ -1203,8 +1201,6 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
if (error)
g_error_free (error);
}
gdk_threads_leave ();
}
static void
@ -1221,16 +1217,12 @@ gtk_file_system_model_query_done (GObject * object,
if (info == NULL)
return;
gdk_threads_enter ();
_gtk_file_system_model_update_file (model, file, info);
id = node_get_for_file (model, file);
gtk_file_system_model_sort_node (model, id);
g_object_unref (info);
gdk_threads_leave ();
}
static void
@ -1255,9 +1247,7 @@ gtk_file_system_model_monitor_change (GFileMonitor * monitor,
model);
break;
case G_FILE_MONITOR_EVENT_DELETED:
gdk_threads_enter ();
remove_file (model, file);
gdk_threads_leave ();
break;
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
/* FIXME: use freeze/thaw with this somehow? */
@ -1280,8 +1270,6 @@ gtk_file_system_model_got_enumerator (GObject *dir, GAsyncResult *res, gpointer
GFileEnumerator *enumerator;
GError *error = NULL;
gdk_threads_enter ();
enumerator = g_file_enumerate_children_finish (G_FILE (dir), res, &error);
if (enumerator == NULL)
{
@ -1310,8 +1298,6 @@ gtk_file_system_model_got_enumerator (GObject *dir, GAsyncResult *res, gpointer
G_CALLBACK (gtk_file_system_model_monitor_change),
model);
}
gdk_threads_leave ();
}
static void

View File

@ -979,11 +979,7 @@ gtk_main (void)
main_loops = g_slist_prepend (main_loops, loop);
if (g_main_loop_is_running (main_loops->data))
{
gdk_threads_leave ();
g_main_loop_run (loop);
gdk_threads_enter ();
}
g_main_loop_run (loop);
main_loops = g_slist_remove (main_loops, loop);
@ -1056,11 +1052,7 @@ gtk_main_sync (void)
g_source_set_name_by_id (store_timeout, "[gtk+] gtk_main_sync clipboard store timeout");
if (g_main_loop_is_running (store.store_loop))
{
gdk_threads_leave ();
g_main_loop_run (store.store_loop);
gdk_threads_enter ();
}
g_main_loop_run (store.store_loop);
g_cancellable_cancel (cancel);
g_object_unref (cancel);
@ -1124,13 +1116,7 @@ gtk_main_quit (void)
gboolean
gtk_events_pending (void)
{
gboolean result;
gdk_threads_leave ();
result = g_main_context_pending (NULL);
gdk_threads_enter ();
return result;
return g_main_context_pending (NULL);
}
/**
@ -1149,9 +1135,7 @@ gtk_events_pending (void)
gboolean
gtk_main_iteration (void)
{
gdk_threads_leave ();
g_main_context_iteration (NULL, TRUE);
gdk_threads_enter ();
if (main_loops)
return !g_main_loop_is_running (main_loops->data);
@ -1173,9 +1157,7 @@ gtk_main_iteration (void)
gboolean
gtk_main_iteration_do (gboolean blocking)
{
gdk_threads_leave ();
g_main_context_iteration (NULL, blocking);
gdk_threads_enter ();
if (main_loops)
return !g_main_loop_is_running (main_loops->data);

View File

@ -641,9 +641,7 @@ gtk_native_dialog_run (GtkNativeDialog *self)
gtk_native_dialog_show (self);
gdk_threads_leave ();
g_main_loop_run (priv->run_loop);
gdk_threads_enter ();
g_signal_handler_disconnect (self, response_handler);

View File

@ -1267,10 +1267,7 @@ gtk_enumerate_printers (GtkPrinterFunc func,
if (wait && printer_list->backends)
{
printer_list->loop = g_main_loop_new (NULL, FALSE);
gdk_threads_leave ();
g_main_loop_run (printer_list->loop);
gdk_threads_enter ();
}
}

View File

@ -268,11 +268,7 @@ portal_end_run (GtkPrintOperation *op,
{
g_object_ref (op);
if (!op_portal->file_written)
{
gdk_threads_leave ();
g_main_loop_run (op_portal->loop);
gdk_threads_enter ();
}
g_main_loop_run (op_portal->loop);
g_object_unref (op);
}
}
@ -644,9 +640,7 @@ gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
call_prepare_print (op, portal);
gdk_threads_leave ();
g_main_loop_run (portal->loop);
gdk_threads_enter ();
*do_print = portal->do_print;
result = portal->result;

View File

@ -390,11 +390,7 @@ unix_end_run (GtkPrintOperation *op,
{
g_object_ref (op);
if (!op_unix->data_sent)
{
gdk_threads_leave ();
g_main_loop_run (op_unix->loop);
gdk_threads_enter ();
}
g_main_loop_run (op_unix->loop);
g_main_loop_unref (op_unix->loop);
op_unix->loop = NULL;
g_object_unref (op);
@ -881,10 +877,7 @@ gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
find_printer (printer_name,
(GFunc) found_printer, &rdata);
gdk_threads_leave ();
g_main_loop_run (rdata.loop);
gdk_threads_enter ();
g_main_loop_unref (rdata.loop);
rdata.loop = NULL;
}

View File

@ -3088,12 +3088,11 @@ print_pages (GtkPrintOperation *op,
priv->rloop = g_main_loop_new (NULL, FALSE);
g_object_ref (op);
gdk_threads_leave ();
g_main_loop_run (priv->rloop);
gdk_threads_enter ();
g_main_loop_unref (priv->rloop);
priv->rloop = NULL;
g_object_unref (op);
}
}

View File

@ -546,9 +546,7 @@ gtk_recent_manager_monitor_changed (GFileMonitor *monitor,
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_DELETED:
gdk_threads_enter ();
gtk_recent_manager_changed (manager);
gdk_threads_leave ();
break;
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
@ -814,8 +812,6 @@ gtk_recent_manager_add_item_query_info (GObject *source_object,
recent_data.groups = NULL;
recent_data.is_private = FALSE;
gdk_threads_enter ();
/* Ignore return value, this can't fail anyway since all required
* fields are set
*/
@ -824,8 +820,6 @@ gtk_recent_manager_add_item_query_info (GObject *source_object,
manager->priv->is_dirty = TRUE;
gtk_recent_manager_changed (manager);
gdk_threads_leave ();
g_free (recent_data.mime_type);
g_free (recent_data.app_name);
g_free (recent_data.app_exec);

View File

@ -7074,8 +7074,6 @@ drag_scan_timeout (gpointer data)
GdkRectangle visible_rect;
GdkSeat *seat;
gdk_threads_enter ();
tree_view = GTK_TREE_VIEW (data);
seat = gdk_display_get_default_seat (gtk_widget_get_display (GTK_WIDGET (tree_view)));
@ -7111,8 +7109,6 @@ drag_scan_timeout (gpointer data)
}
}
gdk_threads_leave ();
return TRUE;
}
#endif /* 0 */

View File

@ -201,8 +201,6 @@ on_timeout (gpointer data)
{
GtkImContextMultipress *multipress_context;
gdk_threads_enter ();
multipress_context = GTK_IM_CONTEXT_MULTIPRESS (data);
/* A certain amount of time has passed, so we will assume that the user
@ -211,8 +209,6 @@ on_timeout (gpointer data)
multipress_context->timeout_id = 0;
gdk_threads_leave ();
return G_SOURCE_REMOVE; /* don't call me again */
}

View File

@ -553,8 +553,6 @@ cups_print_cb (GtkPrintBackendCups *print_backend,
GError *error = NULL;
CupsPrintStreamData *ps = user_data;
gdk_threads_enter ();
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
@ -589,8 +587,6 @@ cups_print_cb (GtkPrintBackendCups *print_backend,
if (error)
g_error_free (error);
gdk_threads_leave ();
}
typedef struct {
@ -1709,12 +1705,10 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend,
int state;
gboolean done;
gdk_threads_enter ();
if (data->job == NULL)
{
cups_job_poll_data_free (data);
goto done;
return;
}
data->counter++;
@ -1781,9 +1775,6 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend,
}
else
cups_job_poll_data_free (data);
done:
gdk_threads_leave ();
}
static void
@ -2682,8 +2673,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend,
gboolean status_changed = FALSE;
ipp_t *response;
gdk_threads_enter ();
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
@ -2783,8 +2772,6 @@ done:
}
printer_setup_info_free (info);
gdk_threads_leave ();
}
static void
@ -3454,8 +3441,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
gchar *remote_default_printer = NULL;
GList *iter;
gdk_threads_enter ();
list_has_changed = FALSE;
GTK_NOTE (PRINTING,
@ -3669,8 +3654,6 @@ done:
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
#endif
gdk_threads_leave ();
}
static void
@ -3790,8 +3773,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
GtkPrinter *printer;
struct stat data_info;
gdk_threads_enter ();
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
@ -3815,7 +3796,7 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
g_signal_emit_by_name (printer, "details-acquired", success);
goto done;
return;
}
#endif
@ -3846,15 +3827,12 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
GTK_PRINTER_CUPS (printer)->port,
GTK_PRINT_BACKEND_CUPS (gtk_printer_get_backend (printer)));
goto done;
return;
}
#endif
gtk_printer_set_has_details (printer, TRUE);
g_signal_emit_by_name (printer, "details-acquired", TRUE);
done:
gdk_threads_leave ();
}
static gboolean
@ -4204,8 +4182,6 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
ipp_attribute_t *attr;
GtkPrinter *printer;
gdk_threads_enter ();
if (gtk_cups_result_is_error (result))
{
if (gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_AUTH &&
@ -4242,8 +4218,6 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
*/
if (print_backend->list_printers_poll != 0)
cups_request_printer_list (print_backend);
gdk_threads_leave ();
}
static gboolean

View File

@ -378,11 +378,10 @@ typedef struct {
GDestroyNotify dnotify;
} _PrintStreamData;
/* expects GDK lock to be held */
static void
file_print_cb_locked (GtkPrintBackendFile *print_backend,
GError *error,
gpointer user_data)
file_print_cb (GtkPrintBackendFile *print_backend,
GError *error,
gpointer user_data)
{
gchar *uri;
@ -399,7 +398,9 @@ file_print_cb_locked (GtkPrintBackendFile *print_backend,
ps->dnotify (ps->user_data);
gtk_print_job_set_status (ps->job,
(error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED);
(error != NULL)
? GTK_PRINT_STATUS_FINISHED_ABORTED
: GTK_PRINT_STATUS_FINISHED);
recent_manager = gtk_recent_manager_get_default ();
uri = output_file_from_settings (gtk_print_job_get_settings (ps->job), NULL);
@ -412,18 +413,6 @@ file_print_cb_locked (GtkPrintBackendFile *print_backend,
g_free (ps);
}
static void
file_print_cb (GtkPrintBackendFile *print_backend,
GError *error,
gpointer user_data)
{
gdk_threads_enter ();
file_print_cb_locked (print_backend, error, user_data);
gdk_threads_leave ();
}
static gboolean
file_write (GIOChannel *source,
GIOCondition con,
@ -515,8 +504,8 @@ gtk_print_backend_file_print_stream (GtkPrintBackend *print_backend,
error:
if (internal_error != NULL)
{
file_print_cb_locked (GTK_PRINT_BACKEND_FILE (print_backend),
internal_error, ps);
file_print_cb (GTK_PRINT_BACKEND_FILE (print_backend),
internal_error, ps);
g_error_free (internal_error);
return;