mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Warn about using an unsafe +initialize
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@32455 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
360e28f269
commit
03233198f7
7 changed files with 7932 additions and 7227 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2011-03-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSUserDefaults.m: Small optimisation suggested by Fred.
|
||||
* config/config.initialize.m: Test for working +initialize
|
||||
* configure.ac: Use test for +initialize thread safety
|
||||
* Headers/Additions/GNUstepBase/config.h.in: regenerate
|
||||
* configure: regenerate
|
||||
* Source/NSThread.m: Log warning when going multithreaded without
|
||||
a reliable runtime.
|
||||
|
||||
2011-03-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSNumberFormatter.m: Make error text compatible with OSX
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/* Headers/Additions/GNUstepBase/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||
|
||||
/* The normal alignment of `pthread_cond_t', in bytes. */
|
||||
#undef ALIGNOF_PTHREAD_COND_T
|
||||
|
||||
|
@ -283,6 +286,9 @@
|
|||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
#undef HAVE_INET_PTON
|
||||
|
||||
/* Define if libobjc has thread-safe +initialize support */
|
||||
#undef HAVE_INITIALIZE
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
|
@ -723,26 +729,44 @@
|
|||
/* Define if using the libffi library for invocations */
|
||||
#undef USE_LIBFFI
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if vasprintf returns the length printed */
|
||||
#undef VASPRINTF_RETURNS_LENGTH
|
||||
|
||||
/* Define if vsprintf returns the length printed */
|
||||
#undef VSPRINTF_RETURNS_LENGTH
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* Define to 1 if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
We just want to avoid a redefinition error message. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
# undef WORDS_BIGENDIAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
|
@ -755,17 +779,6 @@
|
|||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* Enable extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
|
|
|
@ -380,15 +380,13 @@ gnustep_base_thread_callback(void)
|
|||
* Won't work properly if threads are not all created
|
||||
* by this class, but it's better than nothing.
|
||||
*/
|
||||
// FIXME: This code is complete nonsense; this can be called from
|
||||
// any thread (and is when adding new foreign threads), so this
|
||||
// will often be called from the wrong thread, delivering
|
||||
// notifications to the wrong thread, and generally doing the
|
||||
// wrong thing..
|
||||
if (nc == nil)
|
||||
{
|
||||
nc = RETAIN([NSNotificationCenter defaultCenter]);
|
||||
}
|
||||
#if !defined(HAVE_INITIALIZE)
|
||||
NSLog(@"WARNING your program is becoming multi-threaded, but you are using an ObjectiveC runtime library which does not have a thread-safe implementation of the +initialize method. This means that any classes not already used may be incorrectly initialised, potentially causing strange behaviors and crashes. Please build/run GNUstep-base with a runtime which supports the +initialize method.");
|
||||
#endif
|
||||
[nc postNotificationName: NSWillBecomeMultiThreadedNotification
|
||||
object: nil
|
||||
userInfo: nil];
|
||||
|
@ -536,11 +534,7 @@ unregisterActiveThread(NSThread *thread)
|
|||
* if we have become multi-threaded due to a call to the runtime directly
|
||||
* rather than via the NSThread class.
|
||||
*/
|
||||
#if defined(__GNUSTEP_RUNTIME__) || defined(NeXT_RUNTIME)
|
||||
gnustep_base_thread_callback();
|
||||
#else
|
||||
objc_set_thread_callback(gnustep_base_thread_callback);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -783,15 +783,15 @@ newLanguages(NSArray *oldNames)
|
|||
|
||||
+ (NSArray*) userLanguages
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults]
|
||||
stringArrayForKey: @"NSLanguages"];
|
||||
return [[self standardUserDefaults] stringArrayForKey: @"NSLanguages"];
|
||||
}
|
||||
|
||||
+ (void) setUserLanguages: (NSArray*)languages
|
||||
{
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
NSUserDefaults *defs;
|
||||
NSMutableDictionary *dict;
|
||||
|
||||
defs = [self standardUserDefaults];
|
||||
dict = [[defs volatileDomainForName: GSPrimaryDomain] mutableCopy];
|
||||
if (languages == nil) // Remove the entry
|
||||
{
|
||||
|
|
82
config/config.initialize.m
Normal file
82
config/config.initialize.m
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* Test whether Objective-C runtime +initialize support is thread-safe
|
||||
*/
|
||||
|
||||
#include "objc-common.g"
|
||||
#include <pthread.h>
|
||||
|
||||
static unsigned initialize_entered = 0;
|
||||
static unsigned initialize_exited = 0;
|
||||
static unsigned class_entered = 0;
|
||||
static BOOL may_proceed = NO;
|
||||
|
||||
@interface MyClass : NSObject
|
||||
@end
|
||||
@implementation MyClass
|
||||
+ (void) initialize
|
||||
{
|
||||
initialize_entered++;
|
||||
while (NO == may_proceed)
|
||||
sleep(1);
|
||||
initialize_exited++;
|
||||
}
|
||||
+ (Class) class
|
||||
{
|
||||
class_entered++;
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
static void test(void *arg)
|
||||
{
|
||||
[MyClass class];
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t t1;
|
||||
pthread_t t2;
|
||||
|
||||
if (0 == pthread_create(&t1, 0, test, 0))
|
||||
{
|
||||
unsigned counter = 0;
|
||||
|
||||
while (0 == initialize_entered && counter++ < 3)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
if (0 == initialize_entered)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize\n");
|
||||
return 1;
|
||||
}
|
||||
if (0 == pthread_create(&t1, 0, test, 0))
|
||||
{
|
||||
sleep(1);
|
||||
if (class_entered > 0)
|
||||
{
|
||||
fprintf(stderr, "class entered prematurely\n");
|
||||
return 1;
|
||||
}
|
||||
may_proceed = YES;
|
||||
sleep(1);
|
||||
if (2 == class_entered)
|
||||
{
|
||||
return 0; // OK
|
||||
}
|
||||
fprintf(stderr, "problem with initialize\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "failed to create t2\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "failed to create t1\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
142
configure.ac
142
configure.ac
|
@ -1457,6 +1457,66 @@ OBJC_SYS_DYNAMIC_LINKER()
|
|||
# NOTE: libdl should be in LIBS now if it's available.
|
||||
AC_CHECK_FUNCS(dladdr)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for pthread.h
|
||||
#--------------------------------------------------------------------
|
||||
AC_CHECK_HEADERS(pthread.h)
|
||||
if test $ac_cv_header_pthread_h = yes ; then
|
||||
AC_CHECK_SIZEOF(pthread_mutex_t,,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
|
||||
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find size of pthread_mutex_t (required).])
|
||||
fi
|
||||
AC_SUBST(GS_SIZEOF_MUTEX_T)
|
||||
AC_CHECK_SIZEOF(pthread_cond_t,,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find size of pthread_cond_t (required).])
|
||||
fi
|
||||
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
|
||||
AC_SUBST(GS_SIZEOF_COND_T)
|
||||
AC_CHECK_ALIGNOF(pthread_mutex_t,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
|
||||
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find align of pthread_mutex_t (required).])
|
||||
fi
|
||||
AC_SUBST(GS_ALIGNOF_MUTEX_T)
|
||||
AC_CHECK_ALIGNOF(pthread_cond_t,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find align of pthread_cond_t (required).])
|
||||
fi
|
||||
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
|
||||
AC_SUBST(GS_ALIGNOF_COND_T)
|
||||
else
|
||||
AC_MSG_ERROR([Unable to find pthread.h (needed for thread support).])
|
||||
fi
|
||||
AC_CHECK_LIB(pthread, pthread_join, pthread_ok=yes, pthread_ok=no)
|
||||
ismingw=no
|
||||
case "$target_os" in
|
||||
mingw*) ismingw=yes;;
|
||||
esac
|
||||
if test $pthread_ok = yes ; then
|
||||
LIBS="$LIBS -lpthread"
|
||||
else
|
||||
if test $ismingw = yes ; then
|
||||
AC_CHECK_LIB(pthreadGC2, pthread_join, pthread_ok=yes, pthread_ok=no)
|
||||
if test $pthread_ok = yes ; then
|
||||
LIBS="$LIBS -lpthreadGC2"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test $pthread_ok = no ; then
|
||||
AC_MSG_ERROR([Unable to find pthread library (needed for thread support).])
|
||||
fi
|
||||
|
||||
|
||||
# Typically need librt on Solaris for sched_yield
|
||||
AC_CHECK_LIB(rt, sched_yield)
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether Objective-C /really/ works
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -1570,6 +1630,8 @@ else
|
|||
fi
|
||||
AC_SUBST(OBJCSYNC)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for ObjC2 support in runtime
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -1581,6 +1643,8 @@ else
|
|||
fi
|
||||
AC_SUBST(OBJC2RUNTIME)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
GS_NONFRAGILE=0
|
||||
GS_MIXEDABI=0
|
||||
if test "$nonfragile" = "yes"; then
|
||||
|
@ -1632,6 +1696,8 @@ if test $have_set_uncaught_exception_handler = yes; then
|
|||
fi
|
||||
AC_MSG_RESULT($have_set_uncaught_exception_handler)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
AC_MSG_CHECKING(for objc_set_unexpected() in runtime)
|
||||
AC_LINK_IFELSE([#include "$srcdir/config/config.set_unexpected.m"],
|
||||
have_set_unexpected=yes, have_set_unexpected=no)
|
||||
|
@ -1641,6 +1707,8 @@ if test $have_set_unexpected = yes; then
|
|||
fi
|
||||
AC_MSG_RESULT($have_set_unexpected)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
AC_MSG_CHECKING(for _objc_unexpected_exception in runtime)
|
||||
AC_RUN_IFELSE([#include "$srcdir/config/config.unexpected.m"],
|
||||
have_unexpected=yes, have_unexpected=no)
|
||||
|
@ -1671,6 +1739,19 @@ if test $ac_cv_func_objc_sync_enter = yes ; then
|
|||
fi
|
||||
AC_SUBST(HAVE_OBJC_SYNC_ENTER)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
AC_MSG_CHECKING(for thread-safe +initialize in runtime)
|
||||
AC_RUN_IFELSE([#include "$srcdir/config/config.initialize.m"],
|
||||
safe_initialize=yes, safe_initialize=no)
|
||||
if test $safe_initialize = yes; then
|
||||
AC_DEFINE(HAVE_INITIALIZE,1,
|
||||
[Define if libobjc has thread-safe +initialize support])
|
||||
else
|
||||
AC_MSG_WARN([Your ObjectiveC runtime does not support thread-safe class initialisation. Please use a different runtime if you intend to use threads.])
|
||||
fi
|
||||
AC_MSG_RESULT($safe_initialize)
|
||||
|
||||
LIBS="$saved_LIBS"
|
||||
CPPFLAGS="$saved_CPPFLAGS"
|
||||
|
||||
|
@ -1805,64 +1886,6 @@ if test $ac_cv_header_poll_h = yes; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for pthread.h
|
||||
#--------------------------------------------------------------------
|
||||
AC_CHECK_HEADERS(pthread.h)
|
||||
if test $ac_cv_header_pthread_h = yes ; then
|
||||
AC_CHECK_SIZEOF(pthread_mutex_t,,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
|
||||
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find size of pthread_mutex_t (required).])
|
||||
fi
|
||||
AC_SUBST(GS_SIZEOF_MUTEX_T)
|
||||
AC_CHECK_SIZEOF(pthread_cond_t,,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find size of pthread_cond_t (required).])
|
||||
fi
|
||||
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
|
||||
AC_SUBST(GS_SIZEOF_COND_T)
|
||||
AC_CHECK_ALIGNOF(pthread_mutex_t,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
|
||||
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find align of pthread_mutex_t (required).])
|
||||
fi
|
||||
AC_SUBST(GS_ALIGNOF_MUTEX_T)
|
||||
AC_CHECK_ALIGNOF(pthread_cond_t,[AC_INCLUDES_DEFAULT
|
||||
#include <pthread.h>])
|
||||
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
|
||||
AC_MSG_ERROR([Unable to find align of pthread_cond_t (required).])
|
||||
fi
|
||||
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
|
||||
AC_SUBST(GS_ALIGNOF_COND_T)
|
||||
else
|
||||
AC_MSG_ERROR([Unable to find pthread.h (needed for thread support).])
|
||||
fi
|
||||
AC_CHECK_LIB(pthread, pthread_join, pthread_ok=yes, pthread_ok=no)
|
||||
ismingw=no
|
||||
case "$target_os" in
|
||||
mingw*) ismingw=yes;;
|
||||
esac
|
||||
if test $pthread_ok = yes ; then
|
||||
LIBS="$LIBS -lpthread"
|
||||
else
|
||||
if test $ismingw = yes ; then
|
||||
AC_CHECK_LIB(pthreadGC2, pthread_join, pthread_ok=yes, pthread_ok=no)
|
||||
if test $pthread_ok = yes ; then
|
||||
LIBS="$LIBS -lpthreadGC2"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test $pthread_ok = no ; then
|
||||
AC_MSG_ERROR([Unable to find pthread library (needed for thread support).])
|
||||
fi
|
||||
|
||||
# Typically need librt on Solaris for sched_yield
|
||||
AC_CHECK_LIB(rt, sched_yield)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# This function needed by StdioStream.m
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -2212,8 +2235,7 @@ elif test "$enable_pass_arguments" = "no"; then
|
|||
if test "$objc_load_method_worked" = yes -a \( "$ac_cv_sys_procfs" = yes -o "$have_kvm_env" = 1 -o "$ac_cv_sys_procfs_psinfo" = yes \); then
|
||||
GS_FAKE_MAIN=0
|
||||
if test "$have_kvm_env" = "1"; then
|
||||
echo "WARNING ... using libkvm which is known to be buggy on some systems"
|
||||
echo "consider configuring with --enable-fake-main instead."
|
||||
AC_MSG_WARN([Using libkvm which is known to be buggy on some systems consider configuring with --enable-fake-main instead.])
|
||||
fi
|
||||
else
|
||||
GS_FAKE_MAIN=1
|
||||
|
|
Loading…
Reference in a new issue