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
> 

------------------------------------------------------------------------------
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

Reply via email to