cli: fix saving connections in the connection editor

- Main command loop was moved to run in a separate thread (using GThread).
  Otherwise glib main loop would be blocked in processing D-Bus and other
  events.
- Handle creating new vs. updating already saved connection.
This commit is contained in:
Jiří Klimeš
2013-03-21 17:08:44 +01:00
parent 07c92ec6e7
commit 6f883c310e

View File

@@ -3654,6 +3654,44 @@ editor_sub_usage (const char *command)
/*----------------------------------------------------------------------------*/
static gboolean nmc_editor_cb_called;
static GError *nmc_editor_error;
static GMutex nmc_editor_mutex;
static GCond nmc_editor_cond;
/*
* Store 'error' to shared 'nmc_editor_error' and signal the condition
* so that the 'editor-thread' thread could process that.
*/
static void
set_and_signal_error (GError *error)
{
g_mutex_lock (&nmc_editor_mutex);
nmc_editor_cb_called = TRUE;
nmc_editor_error = error ? g_error_copy (error) : NULL;
g_cond_signal (&nmc_editor_cond);
g_mutex_unlock (&nmc_editor_mutex);
}
static void
add_connection_editor_cb (NMRemoteSettings *settings,
NMRemoteConnection *connection,
GError *error,
gpointer user_data)
{
set_and_signal_error (error);
}
static void
update_connection_editor_cb (NMRemoteConnection *connection,
GError *error,
gpointer user_data)
{
set_and_signal_error (error);
}
/*----------------------------------------------------------------------------*/
static void
print_property_description (NMSetting *setting, const char *prop_name)
{
@@ -3997,6 +4035,7 @@ menu_switch_to_level1 (NmcEditorMenuContext *menu_ctx,
static gboolean
editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
{
NMRemoteConnection *rem_con = NULL;
NmcEditorMainCmd cmd;
char *cmd_user;
gboolean cmd_loop = TRUE;
@@ -4022,6 +4061,9 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
menu_ctx.valid_props_str = NULL;
while (cmd_loop) {
if (!rem_con)
rem_con = nm_remote_settings_get_connection_by_uuid (nmc->system_settings,
nm_connection_get_uuid (connection));
cmd_user = readline_x (menu_ctx.main_prompt);
if (!cmd_user || *cmd_user == '\0')
continue;
@@ -4293,21 +4335,45 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
case NMC_EDITOR_MAIN_CMD_SAVE:
/* Save the connection */
if (nm_connection_verify (connection, &err1)) {
if (!rem_con) {
/* Tell the settings service to add the new connection */
info = g_malloc0 (sizeof (AddConnectionInfo));
info->nmc = nmc;
info->con_name = g_strdup (nm_connection_get_id (connection));
//info->device = device;
/* Tell the settings service to add the new connection */
nm_remote_settings_add_connection (nmc->system_settings,
connection,
add_connection_cb,
add_connection_editor_cb,
info);
} else {
/* Save/update already saved (existing) connection */
nm_connection_replace_settings_from_connection (NM_CONNECTION (rem_con),
connection,
NULL);
nm_remote_connection_commit_changes (rem_con,
update_connection_editor_cb,
NULL);
}
// FIXME: we should run cmd loop in a thread of something,
// because the current way blocks glib main loop, and thus D-Bus
// callbacks (and all other events) can't be processed !!!
g_mutex_lock (&nmc_editor_mutex);
//FIXME: add also a timeout for cases the callback is not called
while (!nmc_editor_cb_called)
g_cond_wait (&nmc_editor_cond, &nmc_editor_mutex);
if (nmc_editor_error) {
printf (_("Error: Failed to save '%s' (%s) connection: (%d) %s\n"),
nm_connection_get_id (connection),
nm_connection_get_uuid (connection),
nmc_editor_error->code, nmc_editor_error->message);
g_error_free (nmc_editor_error);
} else
printf (_("Connection '%s' (%s) sucessfully saved.\n"),
nm_connection_get_id (connection),
nm_connection_get_uuid (connection));
nmc_editor_cb_called = FALSE;
nmc_editor_error = NULL;
g_mutex_unlock (&nmc_editor_mutex);
} else
printf (_("Error: connection verification failed: %s\n"),
err1 ? err1->message : _("(unknown)"));
@@ -4624,7 +4690,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
if (connection)
g_object_unref (connection);
nmc->should_wait = FALSE;
nmc->should_wait = TRUE;
return nmc->return_value;
error:
@@ -4787,6 +4853,35 @@ do_connection_reload (NmCli *nmc, int argc, char **argv)
return nmc->return_value;
}
typedef struct {
NmCli *nmc;
int argc;
char **argv;
} NmcEditorThreadData;
static GThread *editor_thread;
static NmcEditorThreadData editor_thread_data;
/*
* We need to run do_connection_edit() in a thread so that
* glib main loop is not blocked and could receive and process D-Bus
* return messages.
*/
static gpointer
connection_editor_thread_func (gpointer data)
{
NmcEditorThreadData *td = (NmcEditorThreadData *) data;
/* run editor for editing/adding connections */
td->nmc->return_value = do_connection_edit (td->nmc, td->argc, td->argv);
/* quit glib main loop now that we are with this thread */
quit ();
return NULL;
}
static NMCResultCode
parse_cmd (NmCli *nmc, int argc, char **argv)
{
@@ -4827,7 +4922,11 @@ parse_cmd (NmCli *nmc, int argc, char **argv)
nmc->return_value = do_connection_add (nmc, argc-1, argv+1);
}
else if (matches(*argv, "edit") == 0) {
nmc->return_value = do_connection_edit (nmc, argc-1, argv+1);
editor_thread_data.nmc = nmc;
editor_thread_data.argc = argc - 1;
editor_thread_data.argv = argv + 1;
editor_thread = g_thread_new ("editor-thread", connection_editor_thread_func, &editor_thread_data);
g_thread_unref (editor_thread);
}
else if (matches(*argv, "delete") == 0) {
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);