Ron: I can't create one since it occurs only with the add-in using xharbour builder. I haven't seen that error with xharbour.org compiler since we don't use MT.
Ron Pinkas wrote: > Maurilio, Luis, > > Please post a REDUCED, yet SELF CONTAINED, sample that shows the problem. > > Ron > > -------------------------------------------------- > From: "Luis Krause Mantilla" <lkrau...@shaw.ca> > Sent: Thursday, January 08, 2009 9:27 AM > To: "Maurilio Longo" <maurilio.lo...@libero.it> > Cc: "Xharbour-Developers List" > <xharbour-developers@lists.sourceforge.net>; "Ron Pinkas" > <r...@xharbour.com> > Subject: Re: [xHarbour-developers] MT build dies at startup > >> Ron: >> >> This same problem Maurilio describes occurs with the most current >> builds of xharbour builder and for this reason we can't test the >> Outlook add-in with any recent versions of xbuilder because >> Outlooks bombs upon closing it. >> >> Regards, >> >> Maurilio Longo wrote: >>> I've received a message from Przemyslaw that I attach here, I think >>> we should >>> seriously fix these problems, right now xharbour is not useable >>> anymore, not >>> only in MT mode but even a plain ST code with a destructor (which >>> does not >>> uses statics nor creates now objects inside destructor). >>> >>> Maurilio. >>> >>> >>> Message from Przemyslaw follows >>> --------8<----------------------------- >>> >>> It's causes by: >>> STATIC lInErr >>> inside rtl/terror.prg >>> >>> below I'm forwarding the last message I sent to Phil with a patch >>> which resolves the problem by simple removing lInErr. >>> Please note that there is s_iLaunchCount for protection against >>> recursive >>> error calls inside source/vm/errorapi.c which in MT version is part >>> of HVM >>> stack. >>> >>> The problem with destructors your reported is probably caused by >>> executing destructors also for statics variables. Because class >>> definition is stored inside such variables then it means that now >>> you cannot create any new object inside destructor even if you want >>> to remove it immediately. It also means that you should not expect >>> any valid values in static variables you will want to access from >>> destructors so you should probably not use them in destructors at all. >>> >>> best regards, >>> Przemek >>> >>> >>> ----- Forwarded message from Przemyslaw Czerpak <dru...@acn.waw.pl> >>> ----- >>> >>> From: Przemyslaw Czerpak <dru...@acn.waw.pl> >>> Subject: Re: [xHarbour-developers] ChangeLog 2008-12-23 01:00 UTC+0300 >>> PhilKrylov <phil a t newstar.rinet.ru> >>> To: Phil Krylov <p...@newstar.rinet.ru> >>> Date: Wed, 24 Dec 2008 03:25:48 +0100 >>> Lines: 131 >>> >>> On Wed, 24 Dec 2008, Przemyslaw Czerpak wrote: >>> >>> Hi Phil, >>> >>> Finally I located the problem with reference counters and why >>> it was crashing in T004. Just simply in some syncing after CVS >>> update I had to add by mistake HB_ATOMIC_INC()/HB_ATOMIC_DEC() >>> macros definition to the section which is used for ST mode. >>> If you moved it then readonly access to complex variables >>> begins to work without crashes. Looking for the problem I also >>> found that hb_itemUnShareString() was copied from Harbour as >>> is without adopting it to xHarbour. I have serious doubts if >>> Miguel well knows what he is doing porting Harbour code only >>> partially. Someone should verify such modifications. >>> I'm attaching patch which resolves this problems and speedtst.prg >>> begins to work with xHarbour. But it was rather trivial things. >>> Now you should look for much more complicated ones. F.e. race >>> conditions when threads are started/finished which causes that >>> programs creating simultaneously many short life threads crashes, >>> memvar variables which causes unreported memory leaks so in practice >>> cannot be use in MT programs which have to be executed for long time >>> creating many threads (each new thread allocates new dynamic symbols >>> for each used memvar which is never released), add MT protection >>> for classy code, remove all global static variables like >>> hb_vm_bQuitRequest, s_iBaseLine, hb_vm_iTry, ... >>> check the .prg code which also uses many static variables >>> (probably you will have to add support for THREAD STATIC if >>> you will want to make some things like GETLIST working in MT >>> mode), make SETs thread local (or any code which have to use >>> them cannot be ported to MT), updated GT code and enable GT >>> locking (f.e. see gtapi.c in Harbour and xHarbour), clean >>> basic thread API to eliminate race conditions which xHarbour >>> thread functions have (see some notes in speedtst.prg), fix >>> some compiler constructions like multivalue macros (f.e.: >>> a[&("1,2")], qout(&("3,4")), a:={&("5,6,7"})] ) or TRY/CATCH >>> which are not MT safe, update debugger for MT mode, reduce >>> number of internal locks which kill scalability - you probably >>> noticed in speedtst results that on real multiCPU machine is >>> more efficient to execute simultaneously 2 * <numCPU> instances >>> of single thread xHarbour program then <numCPU> threads in MT one. >>> Here it will be necessary to strongly change some subsystems. >>> F.e. whole macro compiler is protected by MUTEX so only one thread >>> can access it. To resolve it it's necessary to rewrite compiler, >>> macrocompiler and lexer code to be MT and reentrant safe. >>> And probably many other things I do not remember know. If you >>> are interested then I can try to collect modifications I had >>> to made in Harbour when I was working on MT mode. I still should >>> have a list I created over year ago. >>> They should help you to locate places which should be updated. >>> HTH >>> >>> Marry Christmas and Happy New Year, >>> Przemek >>> >>> >>> * xharbour/config/rules.cf >>> * give PRG_USR higher priority then HB_FLAGS >>> >>> * xharbour/include/thread.h >>> ! fixed declaration of HB_ATOMIC_INC()/HB_ATOMIC_DEC() macros >>> for 32bit x86 *nixes - by mistake it was added to ST section >>> >>> * xharbour/source/rtl/terror.prg >>> ! removed lInErr static variable - it breaks using errorNew() in >>> MT programs >>> >>> * xharbour/source/vm/itemapi.c >>> ! fixed copied as is from Harbour hb_itemUnShareString() >>> Harbour uses different HVM internals and such code cannot >>> be copied without adopting to xHarbour >>> >>> * xharbour/tests/speedtst.prg >>> ! fixed possible race condition in initialization >>> + added SET WORKAREA PRIVATE >>> >>> Index: config/rules.cf >>> =================================================================== >>> RCS file: /cvsroot/xharbour/xharbour/config/rules.cf,v >>> retrieving revision 1.13 >>> diff -u -r1.13 rules.cf >>> --- config/rules.cf 16 Mar 2008 19:15:57 -0000 1.13 >>> +++ config/rules.cf 24 Dec 2008 02:19:44 -0000 >>> @@ -85,7 +85,7 @@ >>> else >>> # Rule to generate a C file from a PRG file. >>> %.c : $(GRANDP)%.prg >>> - $(HB) $? $(PRG_USR) $(HB_FLAGS) >>> + $(HB) $? $(HB_FLAGS) $(PRG_USR) >>> endif >>> >>> ifeq ($(SHLVL),) # COMMAND.COM >>> Index: include/thread.h >>> =================================================================== >>> RCS file: /cvsroot/xharbour/xharbour/include/thread.h,v >>> retrieving revision 1.126 >>> diff -u -r1.126 thread.h >>> --- include/thread.h 23 Dec 2008 18:06:33 -0000 1.126 >>> +++ include/thread.h 24 Dec 2008 02:19:44 -0000 >>> @@ -396,8 +396,37 @@ >>> >>> #endif >>> >>> - #define HB_ATOMIC_INC( x ) ( ++(x) ) >>> - #define HB_ATOMIC_DEC( x ) ( --(x) ) >>> + #if HB_COUNTER_SIZE == 4 && defined( __GNUC__ ) && 1 && \ >>> + ( defined( i386 ) || defined( __i386__ ) || defined( >>> __x86_64__ ) ) >>> + >>> + static __inline__ void hb_atomic_inc32( volatile int * p ) >>> + { >>> + __asm__ __volatile__( >>> + "lock; incl %0\n" >>> + :"=m" (*p) :"m" (*p) >>> + ); >>> + } >>> + >>> + static __inline__ int hb_atomic_dec32( volatile int * p ) >>> + { >>> + unsigned char c; >>> + __asm__ __volatile__( >>> + "lock; decl %0\n" >>> + "sete %1\n" >>> + :"=m" (*p), "=qm" (c) :"m" (*p) : "memory" >>> + ); >>> + return c == 0; >>> + } >>> + >>> + #define HB_ATOMIC_INC( x ) ( hb_atomic_inc32( ( volatile >>> int * ) >>> &(x) ) ) >>> + #define HB_ATOMIC_DEC( x ) ( hb_atomic_dec32( ( volatile >>> int * ) >>> &(x) ) ) >>> + >>> + #else >>> + >>> + #define HB_ATOMIC_INC( x ) ( ++(x) ) >>> + #define HB_ATOMIC_DEC( x ) ( --(x) ) >>> + >>> + #endif >>> >>> #define HB_MUTEX_T HB_CRITICAL_T >>> #define HB_MUTEX_INIT( x ) HB_CRITICAL_INIT( x ) >>> @@ -875,37 +904,8 @@ >>> >>> #else >>> >>> - #if HB_COUNTER_SIZE == 4 && defined( __GNUC__ ) && \ >>> - ( defined( i386 ) || defined( __i386__ ) || defined( >>> __x86_64__ ) ) >>> - >>> - static __inline__ void hb_atomic_inc32( volatile int * p ) >>> - { >>> - __asm__ __volatile__( >>> - "lock; incl %0\n" >>> - :"=m" (*p) :"m" (*p) >>> - ); >>> - } >>> - >>> - static __inline__ int hb_atomic_dec32( volatile int * p ) >>> - { >>> - unsigned char c; >>> - __asm__ __volatile__( >>> - "lock; decl %0\n" >>> - "sete %1\n" >>> - :"=m" (*p), "=qm" (c) :"m" (*p) : "memory" >>> - ); >>> - return c == 0; >>> - } >>> - >>> - #define HB_ATOMIC_INC( x ) ( hb_atomic_inc32( ( volatile >>> int * ) >>> &(x) ) ) >>> - #define HB_ATOMIC_DEC( x ) ( hb_atomic_dec32( ( volatile >>> int * ) >>> &(x) ) ) >>> - >>> - #else >>> - >>> - #define HB_ATOMIC_INC( x ) ( ++(x) ) >>> - #define HB_ATOMIC_DEC( x ) ( --(x) ) >>> - >>> - #endif >>> + #define HB_ATOMIC_INC( x ) ( ++(x) ) >>> + #define HB_ATOMIC_DEC( x ) ( --(x) ) >>> >>> #define HB_CRITICAL_LOCK( x ) >>> #define HB_CRITICAL_TRYLOCK( x ) >>> Index: source/rtl/terror.prg >>> =================================================================== >>> RCS file: /cvsroot/xharbour/xharbour/source/rtl/terror.prg,v >>> retrieving revision 1.19 >>> diff -u -r1.19 terror.prg >>> --- source/rtl/terror.prg 27 Jun 2008 06:21:49 -0000 1.19 >>> +++ source/rtl/terror.prg 24 Dec 2008 02:19:44 -0000 >>> @@ -61,19 +61,12 @@ >>> >>> FUNCTION ErrorNew( SubSystem, GenCode, SubCode, Operation, >>> Description, Args, >>> ModuleName, ProcName, ProcLine ) >>> >>> - STATIC lInErr := .F., s_oClass >>> + STATIC s_oClass >>> LOCAL oErr >>> LOCAL nLevel, aaStack >>> >>> //TraceLog( SubSystem, GenCode, SubCode, Operation, Description, >>> Args, >>> ModuleName, ProcName, ProcLine ) >>> >>> - // Avoid RECURSIVE Errors. >>> - IF lInErr >>> - RETURN NIL >>> - ELSE >>> - lInErr := .T. >>> - ENDIF >>> - >>> IF s_oClass == NIL >>> s_oClass := HBClass():New( "ERROR" ) >>> >>> @@ -160,8 +153,6 @@ >>> oErr:VMThreadId := ThreadGetCurrentInternal() >>> #endif >>> >>> - lInErr := .F. >>> - >>> RETURN oErr >>> >>> FUNCTION __eInstVar53( oVar, cMethod, xValue, cType, nSubCode, >>> bValid ) >>> Index: source/vm/itemapi.c >>> =================================================================== >>> RCS file: /cvsroot/xharbour/xharbour/source/vm/itemapi.c,v >>> retrieving revision 1.155 >>> diff -u -r1.155 itemapi.c >>> --- source/vm/itemapi.c 3 Dec 2008 11:09:45 -0000 1.155 >>> +++ source/vm/itemapi.c 24 Dec 2008 02:19:44 -0000 >>> @@ -1521,14 +1521,19 @@ >>> HB_TRACE_STEALTH(HB_TR_DEBUG, ("hb_itemUnShareString(%p)", pItem)); >>> >>> if( pItem->item.asString.allocated == 0 || >>> - hb_xRefCount( pItem->item.asString.value ) > 1 ) >>> + *( pItem->item.asString.pulHolders ) > 1 ) >>> { >>> ULONG ulLen = pItem->item.asString.length + 1; >>> char *szText = ( char* ) hb_xgrab( ulLen ); >>> >>> hb_xmemcpy( szText, pItem->item.asString.value, ulLen ); >>> if( pItem->item.asString.allocated ) >>> - hb_xRefDec( pItem->item.asString.value ); >>> + { >>> + if( HB_ATOMIC_DEC( *( pItem->item.asString.pulHolders ) ) >>> == 0 ) >>> + { >>> + hb_xfree( pItem->item.asString.value ); >>> + } >>> + } >>> pItem->item.asString.value = szText; >>> pItem->item.asString.allocated = ulLen; >>> } >>> Index: tests/speedtst.prg >>> =================================================================== >>> RCS file: /cvsroot/xharbour/xharbour/tests/speedtst.prg,v >>> retrieving revision 1.8 >>> diff -u -r1.8 speedtst.prg >>> --- tests/speedtst.prg 23 Dec 2008 18:06:33 -0000 1.8 >>> +++ tests/speedtst.prg 24 Dec 2008 02:19:45 -0000 >>> @@ -11,7 +11,6 @@ >>> * >>> */ >>> >>> - >>> #define N_TESTS 54 >>> #define N_LOOPS 1000000 >>> #define ARR_LEN 16 >>> @@ -241,7 +240,13 @@ >>> >>> /* initialize mutex in hb_trheadDoOnce() */ >>> init proc once_init() >>> + set workarea private >>> hb_threadOnce() >>> + /* initialize error object to reduce possible crashes when two >>> + * threads will try to create new error class simultaneously >>> + * xHarbour does not have any protection against such situation >>> + */ >>> + errorNew() >>> return >>> >>> function hb_threadOnce( xOnceControl, bAction ) >>> @@ -253,11 +258,11 @@ >>> if xOnceControl == NIL >>> hb_mutexLock( s_mutex ) >>> if xOnceControl == NIL >>> - xOnceControl := .t. >>> - lFirstCall := .t. >>> if bAction != NIL >>> eval( bAction ) >>> endif >>> + xOnceControl := .t. >>> + lFirstCall := .t. >>> endif >>> hb_mutexUnlock( s_mutex ) >>> endif >>> @@ -275,15 +280,15 @@ >>> TEST t003 WITH L_D:=date() CODE x := L_D >>> >>> TEST t004 INIT _( static s_once, S_C ) ; >>> - INIT iif( hb_threadOnce( @s_once ), S_C := dtos(date()), ) ; >>> + INIT hb_threadOnce( @s_once, {|| S_C := dtos( date() ) } ) ; >>> CODE x := S_C >>> >>> TEST t005 INIT _( static s_once, S_N ) ; >>> - INIT iif( hb_threadOnce( @s_once ), S_N := 112345.67, ) ; >>> + INIT hb_threadOnce( @s_once, {|| S_N := 112345.67 } ) ; >>> CODE x := S_N >>> >>> TEST t006 INIT _( static s_once, S_D ) ; >>> - INIT iif( hb_threadOnce( @s_once ), S_D := date(), ) ; >>> + INIT hb_threadOnce( @s_once, {|| S_D := date() } ) ; >>> CODE x := S_D >>> >>> TEST t007 INIT _( memvar M_C ) INIT _( private M_C := dtos( date() >>> ) ) ; >>> @@ -298,19 +303,19 @@ >>> TEST t010 INIT _( memvar P_C ) ; >>> INIT _( static s_once ) ; >>> INIT _( public P_C ) ; >>> - INIT iif( hb_threadOnce( @s_once ), P_C := dtos( date() >>> ), ) ; >>> + INIT hb_threadOnce( @s_once, {|| P_C := dtos( date() ) } ) ; >>> CODE x := P_C >>> >>> TEST t011 INIT _( memvar P_N ) ; >>> INIT _( static s_once ) ; >>> INIT _( public P_N ) ; >>> - INIT iif( hb_threadOnce( @s_once ), P_N := 112345.67, ) ; >>> + INIT hb_threadOnce( @s_once, {|| P_N := 112345.67 } ) ; >>> CODE x := P_N >>> >>> TEST t012 INIT _( memvar P_D ) ; >>> INIT _( static s_once ) ; >>> INIT _( public P_D ) ; >>> - INIT iif( hb_threadOnce( @s_once ), P_D := date(), ) ; >>> + INIT hb_threadOnce( @s_once, {|| P_D := date() } ) ; >>> CODE x := P_D >>> >>> TEST t013 INIT _( field F_C ) INIT use_dbsh() EXIT close_db() ; >>> >>> >>> ----- End forwarded message ----- >>> >>> >> >> -- >> Luis Krause Mantilla >> lkrausem at shaw dot ca >> luis_krause at hotmail dot com >> "May the Source be with GNU" >> >> >> >> ------------------------------------------------------------------------------ >> >> >> Check out the new SourceForge.net Marketplace. >> It is the best place to buy or sell services for >> just about anything Open Source. >> http://p.sf.net/sfu/Xq1LFB >> _______________________________________________ >> xHarbour-developers mailing list >> xHarbour-developers@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/xharbour-developers >> > -- Luis Krause Mantilla lkrausem at shaw dot ca luis_krause at hotmail dot com "May the Source be with GNU" ------------------------------------------------------------------------------ Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB _______________________________________________ xHarbour-developers mailing list xHarbour-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/xharbour-developers