From d4c1b149fba7ea8a3274b92c622bf672c709f8ad Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Thu, 7 May 2009 23:22:30 +0000 Subject: [PATCH] Make the errno location functions thread safe. Add yktsd.h, which is a heavily pruned copy of Levitte Programming's LPlib file LPthread.h --- configure.ac | 6 +++++ ykcore/ykcore.c | 24 +++++++++++++++----- ykcore/yktsd.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ ykpers.c | 24 +++++++++++++++----- 4 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 ykcore/yktsd.h diff --git a/configure.ac b/configure.ac index 5801933..cb65e92 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,12 @@ AC_SUBST(LT_AGE, 0) AM_INIT_AUTOMAKE([-Wall -Werror]) AC_PROG_CC + +ACX_PTHREAD +LIBS="$PTHREAD_LIBS $LIBS" +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +CC="$PTHREAD_CC" + AC_LIBTOOL_WIN32_DLL AC_PROG_LIBTOOL diff --git a/ykcore/ykcore.c b/ykcore/ykcore.c index ebcf1de..77f2f33 100644 --- a/ykcore/ykcore.c +++ b/ykcore/ykcore.c @@ -30,6 +30,7 @@ #include "ykcore_lcl.h" #include "ykcore_backend.h" +#include "yktsd.h" /* To get modhex and crc16 */ #include @@ -146,14 +147,25 @@ int yk_write_config(YK_KEY *yk, YK_CONFIG *cfg, unsigned char *acc_code) } -/* As soon as we find a way to safely detect if we're in a threaded environment - or not, this should be changed to support per-thread locations. Until then, - we only support non-threaded applications. */ -static int _yk_errno = 0; - int * const _yk_errno_location(void) { - return &_yk_errno; + static int tsd_init = 0; + static int nothread_errno = 0; + YK_DEFINE_TSD_METADATA(errno_key); + int rc = 0; + + if (tsd_init == 0) { + if ((rc = YK_TSD_INIT(errno_key, free)) == 0) { + YK_TSD_SET(errno_key, calloc(1, sizeof(int))); + tsd_init = 1; + } else { + tsd_init = -1; + } + } + if (tsd_init == 1) { + return YK_TSD_GET(int *, errno_key); + } + return ¬hread_errno; } static const char *errtext[] = { diff --git a/ykcore/yktsd.h b/ykcore/yktsd.h new file mode 100644 index 0000000..834a719 --- /dev/null +++ b/ykcore/yktsd.h @@ -0,0 +1,58 @@ +/* yktsd.h -*- mode:C; c-file-style: "gnu" -*- */ +/* Note: this file is copied from Levitte Programming's LPlib and reworked + for ykcore */ +/* + * Copyright (c) 2003, 2004 Richard Levitte . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef YKTSD_H +#define YKTSD_H + +/* Define thread-specific data primitives */ +#if defined _WIN32 +#include +#define yk__TSD_TYPE DWORD +#define yk__TSD_ALLOC(key) ((key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0) +#define yk__TSD_FREE(key) (!TlsFree(key)) +#define yk__TSD_SET(key,value) (!TlsSetValue(key,value)) +#define yk__TSD_GET(key) TlsGetValue(key) +#else +#include +#define yk__TSD_TYPE pthread_key_t +#define yk__TSD_ALLOC(key,destr) pthread_key_create(&key, destr) +#define yk__TSD_FREE(key) pthread_key_delete(key) +#define yk__TSD_SET(key,value) pthread_setspecific(key,(void *)value) +#define yk__TSD_GET(key) pthread_getspecific(key) +#endif + +/* Define the high-level macros that we use. */ +#define YK_TSD_METADATA(x) yk__tsd_##x +#define YK_DEFINE_TSD_METADATA(x) static yk__TSD_TYPE YK_TSD_METADATA(x) +#define YK_TSD_INIT(x,destr) yk__TSD_ALLOC(YK_TSD_METADATA(x),destr) +#define YK_TSD_DESTROY(x) yk__TSD_FREE(YK_TSD_METADATA(x)) +#define YK_TSD_SET(x,value) yk__TSD_SET(YK_TSD_METADATA(x),value) +#define YK_TSD_GET(type,x) (type)yk__TSD_GET(YK_TSD_METADATA(x)) + +#endif diff --git a/ykpers.c b/ykpers.c index 305705c..6c4e1f2 100644 --- a/ykpers.c +++ b/ykpers.c @@ -30,6 +30,7 @@ #include "ykcore_lcl.h" #include "ykpbkdf2.h" +#include "yktsd.h" #include @@ -357,14 +358,25 @@ int ykp_read_config(YK_CONFIG *cfg, return 0; } -/* As soon as we find a way to safely detect if we're in a threaded environment - or not, this should be changed to support per-thread locations. Until then, - we only support non-threaded applications. */ -static int _ykp_errno = 0; - int * const _ykp_errno_location(void) { - return &_ykp_errno; + static int tsd_init = 0; + static int nothread_errno = 0; + YK_DEFINE_TSD_METADATA(errno_key); + int rc = 0; + + if (tsd_init == 0) { + if ((rc = YK_TSD_INIT(errno_key, free)) == 0) { + YK_TSD_SET(errno_key, calloc(1, sizeof(int))); + tsd_init = 1; + } else { + tsd_init = -1; + } + } + if (tsd_init == 1) { + return YK_TSD_GET(int *, errno_key); + } + return ¬hread_errno; } static const char *errtext[] = { -- 2.39.5