diff options
Diffstat (limited to 'src/interfaces/libpq/fe-misc.c')
-rw-r--r-- | src/interfaces/libpq/fe-misc.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 660cdec..488f7d6 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1225,13 +1225,14 @@ static void libpq_binddomain(void) { /* - * If multiple threads come through here at about the same time, it's okay - * for more than one of them to call bindtextdomain(). But it's not okay - * for any of them to return to caller before bindtextdomain() is - * complete, so don't set the flag till that's done. Use "volatile" just - * to be sure the compiler doesn't try to get cute. + * At least on Windows, there are gettext implementations that fail if + * multiple threads call bindtextdomain() concurrently. Use a mutex and + * flag variable to ensure that we call it just once per process. It is + * not known that similar bugs exist on non-Windows platforms, but we + * might as well do it the same way everywhere. */ static volatile bool already_bound = false; + static pthread_mutex_t binddomain_mutex = PTHREAD_MUTEX_INITIALIZER; if (!already_bound) { @@ -1241,14 +1242,26 @@ libpq_binddomain(void) #else int save_errno = errno; #endif - const char *ldir; - - /* No relocatable lookup here because the binary could be anywhere */ - ldir = getenv("PGLOCALEDIR"); - if (!ldir) - ldir = LOCALEDIR; - bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir); - already_bound = true; + + (void) pthread_mutex_lock(&binddomain_mutex); + + if (!already_bound) + { + const char *ldir; + + /* + * No relocatable lookup here because the calling executable could + * be anywhere + */ + ldir = getenv("PGLOCALEDIR"); + if (!ldir) + ldir = LOCALEDIR; + bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir); + already_bound = true; + } + + (void) pthread_mutex_unlock(&binddomain_mutex); + #ifdef WIN32 SetLastError(save_errno); #else |