|
|
ef398b |
From d9571c2f1cf612ce0d479e428f7b1ae24944d140 Mon Sep 17 00:00:00 2001
|
|
|
ef398b |
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
|
ef398b |
Date: Wed, 10 Jun 2020 17:03:28 +0200
|
|
|
ef398b |
Subject: [PATCH] exec: Fix setting locale for util calls
|
|
|
ef398b |
|
|
|
ef398b |
This actually fixes two issue. The _utils_exec_and_report_progress
|
|
|
ef398b |
function didn't set the LC_ALL=C environment variable to make sure
|
|
|
ef398b |
we get output in English. And also we shouldn't use setenv in the
|
|
|
ef398b |
GSpawnChildSetupFunc, it's actually example of what not to do in
|
|
|
ef398b |
g_spawn_async documentation. This fix uses g_environ_setenv and
|
|
|
ef398b |
passes the new environment to the g_spawn call.
|
|
|
ef398b |
---
|
|
|
ef398b |
src/utils/exec.c | 26 +++++++++++++++++---------
|
|
|
ef398b |
tests/utils_test.py | 7 +++++++
|
|
|
ef398b |
2 files changed, 24 insertions(+), 9 deletions(-)
|
|
|
ef398b |
|
|
|
ef398b |
diff --git a/src/utils/exec.c b/src/utils/exec.c
|
|
|
ef398b |
index 9293930..37bd960 100644
|
|
|
ef398b |
--- a/src/utils/exec.c
|
|
|
ef398b |
+++ b/src/utils/exec.c
|
|
|
ef398b |
@@ -140,11 +140,6 @@ static void log_done (guint64 task_id, gint exit_code) {
|
|
|
ef398b |
return;
|
|
|
ef398b |
}
|
|
|
ef398b |
|
|
|
ef398b |
-static void set_c_locale(gpointer user_data __attribute__((unused))) {
|
|
|
ef398b |
- if (setenv ("LC_ALL", "C", 1) != 0)
|
|
|
ef398b |
- g_warning ("Failed to set LC_ALL=C for a child process!");
|
|
|
ef398b |
-}
|
|
|
ef398b |
-
|
|
|
ef398b |
/**
|
|
|
ef398b |
* bd_utils_exec_and_report_error:
|
|
|
ef398b |
* @argv: (array zero-terminated=1): the argv array for the call
|
|
|
ef398b |
@@ -194,6 +189,8 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr
|
|
|
ef398b |
const BDExtraArg **extra_p = NULL;
|
|
|
ef398b |
gint exit_status = 0;
|
|
|
ef398b |
guint i = 0;
|
|
|
ef398b |
+ gchar **old_env = NULL;
|
|
|
ef398b |
+ gchar **new_env = NULL;
|
|
|
ef398b |
|
|
|
ef398b |
if (extra) {
|
|
|
ef398b |
args_len = g_strv_length ((gchar **) argv);
|
|
|
ef398b |
@@ -219,16 +216,20 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr
|
|
|
ef398b |
args[i] = NULL;
|
|
|
ef398b |
}
|
|
|
ef398b |
|
|
|
ef398b |
+ old_env = g_get_environ ();
|
|
|
ef398b |
+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE);
|
|
|
ef398b |
+
|
|
|
ef398b |
task_id = log_running (args ? args : argv);
|
|
|
ef398b |
- success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH,
|
|
|
ef398b |
- (GSpawnChildSetupFunc) set_c_locale, NULL,
|
|
|
ef398b |
- &stdout_data, &stderr_data, &exit_status, error);
|
|
|
ef398b |
+ success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, new_env, G_SPAWN_SEARCH_PATH,
|
|
|
ef398b |
+ NULL, NULL, &stdout_data, &stderr_data, &exit_status, error);
|
|
|
ef398b |
if (!success) {
|
|
|
ef398b |
/* error is already populated from the call */
|
|
|
ef398b |
+ g_strfreev (new_env);
|
|
|
ef398b |
g_free (stdout_data);
|
|
|
ef398b |
g_free (stderr_data);
|
|
|
ef398b |
return FALSE;
|
|
|
ef398b |
}
|
|
|
ef398b |
+ g_strfreev (new_env);
|
|
|
ef398b |
|
|
|
ef398b |
/* g_spawn_sync set the status in the same way waitpid() does, we need
|
|
|
ef398b |
to get the process exit code manually (this is similar to calling
|
|
|
ef398b |
@@ -297,6 +298,8 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
|
|
ef398b |
gboolean err_done = FALSE;
|
|
|
ef398b |
GString *stdout_data = g_string_new (NULL);
|
|
|
ef398b |
GString *stderr_data = g_string_new (NULL);
|
|
|
ef398b |
+ gchar **old_env = NULL;
|
|
|
ef398b |
+ gchar **new_env = NULL;
|
|
|
ef398b |
|
|
|
ef398b |
/* TODO: share this code between functions */
|
|
|
ef398b |
if (extra) {
|
|
|
ef398b |
@@ -325,7 +328,10 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
|
|
ef398b |
|
|
|
ef398b |
task_id = log_running (args ? args : argv);
|
|
|
ef398b |
|
|
|
ef398b |
- ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, NULL,
|
|
|
ef398b |
+ old_env = g_get_environ ();
|
|
|
ef398b |
+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE);
|
|
|
ef398b |
+
|
|
|
ef398b |
+ ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, new_env,
|
|
|
ef398b |
G_SPAWN_DEFAULT|G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
|
|
|
ef398b |
NULL, NULL, &pid, NULL, &out_fd, &err_fd, error);
|
|
|
ef398b |
|
|
|
ef398b |
@@ -333,9 +339,11 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt
|
|
|
ef398b |
/* error is already populated */
|
|
|
ef398b |
g_string_free (stdout_data, TRUE);
|
|
|
ef398b |
g_string_free (stderr_data, TRUE);
|
|
|
ef398b |
+ g_strfreev (new_env);
|
|
|
ef398b |
g_free (args);
|
|
|
ef398b |
return FALSE;
|
|
|
ef398b |
}
|
|
|
ef398b |
+ g_strfreev (new_env);
|
|
|
ef398b |
|
|
|
ef398b |
args_str = g_strjoinv (" ", args ? (gchar **) args : (gchar **) argv);
|
|
|
ef398b |
msg = g_strdup_printf ("Started '%s'", args_str);
|
|
|
ef398b |
diff --git a/tests/utils_test.py b/tests/utils_test.py
|
|
|
ef398b |
index 4bec3db..2bec5ed 100644
|
|
|
ef398b |
--- a/tests/utils_test.py
|
|
|
ef398b |
+++ b/tests/utils_test.py
|
|
|
ef398b |
@@ -170,6 +170,13 @@ class UtilsExecLoggingTest(UtilsTestCase):
|
|
|
ef398b |
# exit code != 0
|
|
|
ef398b |
self.assertTrue(BlockDev.utils_check_util_version("libblockdev-fake-util-fail", "1.1", "version", "Version:\\s(.*)"))
|
|
|
ef398b |
|
|
|
ef398b |
+ @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
|
|
ef398b |
+ def test_exec_locale(self):
|
|
|
ef398b |
+ """Verify that setting locale for exec functions works as expected"""
|
|
|
ef398b |
+
|
|
|
ef398b |
+ succ, out = BlockDev.utils_exec_and_capture_output(["locale"])
|
|
|
ef398b |
+ self.assertTrue(succ)
|
|
|
ef398b |
+ self.assertIn("LC_ALL=C", out)
|
|
|
ef398b |
|
|
|
ef398b |
class UtilsDevUtilsTestCase(UtilsTestCase):
|
|
|
ef398b |
@tag_test(TestTags.NOSTORAGE, TestTags.CORE)
|
|
|
ef398b |
--
|
|
|
ef398b |
2.26.2
|
|
|
ef398b |
|