mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
gutils: avoid race setting prgname from g_option_context_parse()/g_application_run()
g_option_context_parse()/g_application_run()/g_test_init() for convenience also call g_set_prgname(), when the prgname is unset at this point. This was racy. Fix the race by using an atomic compare-and-exchange and only reset the value, if it is unset still.
This commit is contained in:
parent
54e0b2d75b
commit
7098250e7a
@ -38,6 +38,7 @@
|
||||
#include "gioenumtypes.h"
|
||||
#include "gioenums.h"
|
||||
#include "gfile.h"
|
||||
#include "glib-private.h"
|
||||
|
||||
#include "glibintl.h"
|
||||
#include "gmarshal-internal.h"
|
||||
@ -2526,7 +2527,7 @@ g_application_run (GApplication *application,
|
||||
gchar *prgname;
|
||||
|
||||
prgname = g_path_get_basename (argv[0]);
|
||||
g_set_prgname (prgname);
|
||||
GLIB_PRIVATE_CALL (g_set_prgname_once) (prgname);
|
||||
g_free (prgname);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "glib-private.h"
|
||||
#include "glib-init.h"
|
||||
#include "gutilsprivate.h"
|
||||
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
#include <crtdbg.h>
|
||||
@ -71,6 +72,8 @@ glib__private__ (void)
|
||||
g_find_program_for_path,
|
||||
|
||||
g_uri_get_default_scheme_port,
|
||||
|
||||
g_set_prgname_once,
|
||||
};
|
||||
|
||||
return &table;
|
||||
|
@ -288,6 +288,9 @@ typedef struct {
|
||||
/* See guri.c */
|
||||
int (* g_uri_get_default_scheme_port) (const char *scheme);
|
||||
|
||||
/* See gutils.c */
|
||||
gboolean (* g_set_prgname_once) (const gchar *prgname);
|
||||
|
||||
/* Add other private functions here, initialize them in glib-private.c */
|
||||
} GLibPrivateVTable;
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "gprintf.h"
|
||||
#include "glibintl.h"
|
||||
#include "gutilsprivate.h"
|
||||
|
||||
#if defined G_OS_WIN32
|
||||
#include <windows.h>
|
||||
@ -1813,10 +1814,7 @@ g_option_context_parse (GOptionContext *context,
|
||||
else
|
||||
prgname = platform_get_argv0 ();
|
||||
|
||||
if (prgname)
|
||||
g_set_prgname (prgname);
|
||||
else
|
||||
g_set_prgname ("<unknown>");
|
||||
g_set_prgname_once (prgname ? prgname : "<unknown");
|
||||
|
||||
g_free (prgname);
|
||||
}
|
||||
|
@ -1658,7 +1658,7 @@ void
|
||||
}
|
||||
|
||||
if (!g_get_prgname () && !no_g_set_prgname)
|
||||
g_set_prgname ((*argv)[0]);
|
||||
g_set_prgname_once ((*argv)[0]);
|
||||
|
||||
if (g_getenv ("G_TEST_ROOT_PROCESS"))
|
||||
{
|
||||
|
@ -1176,6 +1176,25 @@ g_set_prgname (const gchar *prgname)
|
||||
g_atomic_pointer_set (&g_prgname, prgname);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_set_prgname_once:
|
||||
* @prgname: the name of the program.
|
||||
*
|
||||
* If g_get_prgname() is not set, this is the same as setting
|
||||
* the name via g_set_prgname() and %TRUE is returned. Otherwise,
|
||||
* does nothing and returns %FALSE. This is thread-safe.
|
||||
*
|
||||
* Returns: whether g_prgname was initialized by the call.
|
||||
*/
|
||||
gboolean
|
||||
g_set_prgname_once (const gchar *prgname)
|
||||
{
|
||||
/* if @prgname is NULL, then this has the same effect as calling
|
||||
* (g_get_prgname()==NULL). */
|
||||
prgname = g_intern_string (prgname);
|
||||
return g_atomic_pointer_compare_and_exchange (&g_prgname, NULL, prgname);
|
||||
}
|
||||
|
||||
static gchar *g_application_name = NULL;
|
||||
|
||||
/**
|
||||
|
@ -59,6 +59,8 @@ void _g_unset_cached_tmp_dir (void);
|
||||
|
||||
gboolean _g_localtime (time_t timet, struct tm *tm);
|
||||
|
||||
gboolean g_set_prgname_once (const gchar *prgname);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_UTILS_PRIVATE_H__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user