Blame SOURCES/0001-exec-Fix-setting-locale-for-util-calls.patch

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