@ -7,7 +7,7 @@
*
*
* Portions Copyright ( c ) 1996 - 2003 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1996 - 2003 , PostgreSQL Global Development Group
*
*
* $ PostgreSQL : pgsql / src / port / thread . c , v 1.14 2003 / 11 / 29 22 : 41 : 31 pgsql Exp $
* $ PostgreSQL : pgsql / src / port / thread . c , v 1.15 2004 / 02 / 11 21 : 44 : 06 momjian Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -31,7 +31,7 @@
* strerror ( ) . Other operating systems use pthread_setspecific ( )
* strerror ( ) . Other operating systems use pthread_setspecific ( )
* and pthread_getspecific ( ) internally to allow standard library
* and pthread_getspecific ( ) internally to allow standard library
* functions to return static data to threaded applications . And some
* functions to return static data to threaded applications . And some
* operating systems have neither , meaning we have to do our own locking .
* operating systems have neither .
*
*
* Additional confusion exists because many operating systems that
* Additional confusion exists because many operating systems that
* use pthread_setspecific / pthread_getspecific ( ) also have * _r versions
* use pthread_setspecific / pthread_getspecific ( ) also have * _r versions
@ -50,18 +50,13 @@
*
*
* The current setup is to try threading in this order :
* The current setup is to try threading in this order :
*
*
* use non - * _r function names if they are all thread - safe
* use * _r function names if they exit
* ( NEED_REENTRANT_FUNCS = no )
* ( * _THREADSAFE = ye )
* use * _r functions if they exist ( configure test )
* use non - * _r functions if they are thread - safe
* do our own locking and copying of non - threadsafe functions
*
* The disadvantage of the last option is not the thread overhead but
* the fact that all function calls are serialized , and with gethostbyname ( )
* requiring a DNS lookup , that could be slow .
*
*
* One thread - safe solution for gethostbyname ( ) might be to use getaddrinfo ( ) .
* One thread - safe solution for gethostbyname ( ) might be to use getaddrinfo ( ) .
*
*
* See src / tools / thread to see if your operating system has thread - safe
* Run src / tools / thread to see if your operating system has thread - safe
* non - * _r functions .
* non - * _r functions .
*/
*/
@ -73,7 +68,7 @@
char *
char *
pqStrerror ( int errnum , char * strerrbuf , size_t buflen )
pqStrerror ( int errnum , char * strerrbuf , size_t buflen )
{
{
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined( HAVE_STRERROR_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R)
/* reentrant strerror_r is available */
/* reentrant strerror_r is available */
/* some early standards had strerror_r returning char * */
/* some early standards had strerror_r returning char * */
strerror_r ( errnum , strerrbuf , buflen ) ;
strerror_r ( errnum , strerrbuf , buflen ) ;
@ -81,18 +76,13 @@ pqStrerror(int errnum, char *strerrbuf, size_t buflen)
# else
# else
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(STRERROR_THREADSAFE)
static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER ;
# error This platform can not create a thread-safe version because strerror is not thread-safe and there is no reentrant version
pthread_mutex_lock ( & strerror_lock ) ;
# endif
# endif
/* no strerror_r() available, just use strerror */
/* no strerror_r() available, just use strerror */
StrNCpy ( strerrbuf , strerror ( errnum ) , buflen ) ;
StrNCpy ( strerrbuf , strerror ( errnum ) , buflen ) ;
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R)
pthread_mutex_unlock ( & strerror_lock ) ;
# endif
return strerrbuf ;
return strerrbuf ;
# endif
# endif
}
}
@ -106,7 +96,7 @@ int
pqGetpwuid ( uid_t uid , struct passwd * resultbuf , char * buffer ,
pqGetpwuid ( uid_t uid , struct passwd * resultbuf , char * buffer ,
size_t buflen , struct passwd * * result )
size_t buflen , struct passwd * * result )
{
{
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined( HAVE_GETPWUID_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R)
/*
/*
* Early POSIX draft of getpwuid_r ( ) returns ' struct passwd * ' .
* Early POSIX draft of getpwuid_r ( ) returns ' struct passwd * ' .
* getpwuid_r ( uid , resultbuf , buffer , buflen )
* getpwuid_r ( uid , resultbuf , buffer , buflen )
@ -117,53 +107,14 @@ pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
# else
# else
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(GETPWUID_THREADSAFE)
static pthread_mutex_t getpwuid_lock = PTHREAD_MUTEX_INITIALIZER ;
# error This platform can not create a thread-safe version because getpwuid is not thread-safe and there is no reentrant version
pthread_mutex_lock ( & getpwuid_lock ) ;
# endif
# endif
/* no getpwuid_r() available, just use getpwuid() */
/* no getpwuid_r() available, just use getpwuid() */
* result = getpwuid ( uid ) ;
* result = getpwuid ( uid ) ;
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R)
/* Use 'buffer' memory for storage of strings used by struct passwd */
if ( * result & &
strlen ( ( * result ) - > pw_name ) + 1 +
strlen ( ( * result ) - > pw_passwd ) + 1 +
strlen ( ( * result ) - > pw_gecos ) + 1 +
/* skip class if it exists */
strlen ( ( * result ) - > pw_dir ) + 1 +
strlen ( ( * result ) - > pw_shell ) + 1 < = buflen )
{
memcpy ( resultbuf , * result , sizeof ( struct passwd ) ) ;
strcpy ( buffer , ( * result ) - > pw_name ) ;
resultbuf - > pw_name = buffer ;
buffer + = strlen ( resultbuf - > pw_name ) + 1 ;
strcpy ( buffer , ( * result ) - > pw_passwd ) ;
resultbuf - > pw_passwd = buffer ;
buffer + = strlen ( resultbuf - > pw_passwd ) + 1 ;
strcpy ( buffer , ( * result ) - > pw_gecos ) ;
resultbuf - > pw_gecos = buffer ;
buffer + = strlen ( resultbuf - > pw_gecos ) + 1 ;
strcpy ( buffer , ( * result ) - > pw_dir ) ;
resultbuf - > pw_dir = buffer ;
buffer + = strlen ( resultbuf - > pw_dir ) + 1 ;
strcpy ( buffer , ( * result ) - > pw_shell ) ;
resultbuf - > pw_shell = buffer ;
buffer + = strlen ( resultbuf - > pw_shell ) + 1 ;
* result = resultbuf ;
}
else
{
* result = NULL ;
errno = ERANGE ;
}
pthread_mutex_unlock ( & getpwuid_lock ) ;
# endif
# endif
# endif
return ( * result = = NULL ) ? - 1 : 0 ;
return ( * result = = NULL ) ? - 1 : 0 ;
}
}
# endif
# endif
@ -181,7 +132,7 @@ pqGethostbyname(const char *name,
struct hostent * * result ,
struct hostent * * result ,
int * herrno )
int * herrno )
{
{
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined( HAVE_GETHOSTBYNAME_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
/*
/*
* broken ( well early POSIX draft ) gethostbyname_r ( ) which returns
* broken ( well early POSIX draft ) gethostbyname_r ( ) which returns
* ' struct hostent * '
* ' struct hostent * '
@ -191,87 +142,16 @@ pqGethostbyname(const char *name,
# else
# else
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R)
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(GETHOSTBYNAME_THREADSAFE)
static pthread_mutex_t gethostbyname_lock = PTHREAD_MUTEX_INITIALIZER ;
# error This platform can not create a thread-safe version because getaddrinfo is not thread-safe and there is no reentrant version
pthread_mutex_lock ( & gethostbyname_lock ) ;
# endif
# endif
/* no gethostbyname_r(), just use gethostbyname() */
/* no gethostbyname_r(), just use gethostbyname() */
* result = gethostbyname ( name ) ;
* result = gethostbyname ( name ) ;
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R)
/*
* Use ' buffer ' memory for storage of structures used by struct hostent .
* The layout is :
*
* addr pointers
* alias pointers
* addr structures
* alias structures
* name
*/
if ( * result )
{
int i , pointers = 2 /* for nulls */ , len = 0 ;
char * * pbuffer ;
for ( i = 0 ; ( * result ) - > h_addr_list [ i ] ; i + + , pointers + + )
len + = ( * result ) - > h_length ;
for ( i = 0 ; ( * result ) - > h_aliases [ i ] ; i + + , pointers + + )
len + = ( * result ) - > h_length ;
if ( pointers * sizeof ( char * ) + MAXALIGN ( len ) + strlen ( ( * result ) - > h_name ) + 1 < = buflen )
{
memcpy ( resultbuf , * result , sizeof ( struct hostent ) ) ;
pbuffer = ( char * * ) buffer ;
resultbuf - > h_addr_list = pbuffer ;
buffer + = pointers * sizeof ( char * ) ;
for ( i = 0 ; ( * result ) - > h_addr_list [ i ] ; i + + , pbuffer + + )
{
memcpy ( buffer , ( * result ) - > h_addr_list [ i ] , ( * result ) - > h_length ) ;
resultbuf - > h_addr_list [ i ] = buffer ;
buffer + = ( * result ) - > h_length ;
}
resultbuf - > h_addr_list [ i ] = NULL ;
pbuffer + + ;
resultbuf - > h_aliases = pbuffer ;
for ( i = 0 ; ( * result ) - > h_aliases [ i ] ; i + + , pbuffer + + )
{
memcpy ( buffer , ( * result ) - > h_aliases [ i ] , ( * result ) - > h_length ) ;
resultbuf - > h_aliases [ i ] = buffer ;
buffer + = ( * result ) - > h_length ;
}
resultbuf - > h_aliases [ i ] = NULL ;
pbuffer + + ;
/* Place at end for cleaner alignment */
buffer = MAXALIGN ( buffer ) ;
strcpy ( buffer , ( * result ) - > h_name ) ;
resultbuf - > h_name = buffer ;
buffer + = strlen ( resultbuf - > h_name ) + 1 ;
* result = resultbuf ;
}
else
{
* result = NULL ;
errno = ERANGE ;
}
}
# endif
if ( * result ! = NULL )
if ( * result ! = NULL )
* herrno = h_errno ;
* herrno = h_errno ;
# if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R)
pthread_mutex_unlock ( & gethostbyname_lock ) ;
# endif
if ( * result ! = NULL )
if ( * result ! = NULL )
return 0 ;
return 0 ;
else
else