diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 226ff58f1b..08def09c39 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,34 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-10-13 20:21 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rdd/wacore.c + ; updated comments about xbase++ behavior in dbRelease() + + * harbour/include/hbvm.h + * harbour/source/vm/hvm.c + * harbour/source/vm/dynlibhb.c + * harbour/source/vm/runner.c + ! added MT protection for HB_LIBLOAD()/HB_LIBFREE() and + HB_HRBLOAD()/HB_HRBUNLOAD(). Please remember that you should + not use any external LoadLibrary() functions because they are + not protected for clean PCODE modules loading/unloading even + in ST mode. Using them can cause HVM internal structure corruption. + If we have such functions in contrib then they should be redirected + to our HVM ones. + There is still one problem in MT mode which has to be resolved yet. + When dynamic library containing PCODE using static variables + is loaded 1-st time then it will force resizing of internal array + with static variables. If in exactly the same moment some other + thread operates on static variable then it may cause corruption. + To resolve this problem we will have to divide continuous memory + block common for all modules where we store all static variables + into separated blocks bound with each PCODE module (symbol table). + + * harbour/source/vm/dynlibhb.c + + added support for DLL loading/unloading in OS2 builds. + Based on xHarbour code by Maurilio Longo - please test. + 2008-10-13 20:19 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * contrib/hbmisc/strfmt.c ! Fixed GPF when non-string was passed as diff --git a/harbour/include/hbvm.h b/harbour/include/hbvm.h index 1db69976a0..ea3f89afdd 100644 --- a/harbour/include/hbvm.h +++ b/harbour/include/hbvm.h @@ -89,6 +89,8 @@ extern HB_EXPORT PHB_SYMB hb_vmProcessDynLibSymbols( PHB_SYMB pSymbols, USHORT u } HB_SYMBOLS, * PHB_SYMBOLS; /* structure to keep track of all modules symbol tables */ extern PHB_SYMBOLS hb_vmRegisterSymbols( PHB_SYMB pModuleSymbols, USHORT uiSymbols, const char * szModuleName, ULONG ulID, BOOL fDynLib, BOOL fClone ); + extern BOOL hb_vmLockModuleSymbols( void ); + extern void hb_vmUnlockModuleSymbols( void ); extern void hb_vmFreeSymbols( PHB_SYMBOLS pSymbols ); extern void hb_vmBeginSymbolGroup( void * hDynLib, BOOL fClone ); extern void hb_vmInitSymbolGroup( void * hNewDynLib, int argc, char * argv[] ); diff --git a/harbour/source/rdd/wacore.c b/harbour/source/rdd/wacore.c index e8df689293..5967711817 100644 --- a/harbour/source/rdd/wacore.c +++ b/harbour/source/rdd/wacore.c @@ -515,17 +515,24 @@ HB_EXPORT ERRCODE hb_rddDetachArea( AREAP pArea, PHB_ITEM pCargo ) hb_rddSelectWorkAreaNumber( pArea->uiArea ); /* flush buffers */ SELF_GOCOLD( pArea ); - /* remove all locks */ - /* ??? is it xbase++ compatible? */ + + /* tests shows that xbase++ does not remove locks */ /* SELF_UNLOCK( pArea, NULL ); */ - /* Clear all child and parent relations */ + + /* xbase++ documentation says that child area are also detached but + * but tests shows that it's not true and chilled and parent relations + * are still active and corresponding WA are not detached together. + * Harbour clears all child and parent relations. + */ SELF_CLEARREL( pArea ); hb_rddCloseAllParentRelations( pArea ); + /* detach WA and alias */ hb_waNodeDelete( hb_stackRDD() ); pArea->uiArea = 0; if( pArea->atomAlias ) hb_dynsymSetAreaHandle( ( PHB_DYNS ) pArea->atomAlias, 0 ); + /* restore previous WA number */ hb_rddSelectWorkAreaNumber( iArea ); diff --git a/harbour/source/vm/dynlibhb.c b/harbour/source/vm/dynlibhb.c index e06f1b71de..fd70b212dc 100644 --- a/harbour/source/vm/dynlibhb.c +++ b/harbour/source/vm/dynlibhb.c @@ -67,27 +67,16 @@ # include #endif -/* This releases regex when called from the garbage collector */ static HB_GARBAGE_FUNC( hb_libRelease ) { /* do nothing */ HB_SYMBOL_UNUSED( Cargo ); } -#if defined(HB_OS_WIN_32) || ( defined(HB_OS_LINUX) && !defined(__WATCOMC__) ) -static void * hb_parlib( int iParam ) -{ - void ** pDynLibPtr = ( void ** ) hb_parptrGC( hb_libRelease, iParam ); - - return pDynLibPtr ? * pDynLibPtr : NULL; -} -#endif - HB_FUNC( HB_LIBLOAD ) { void * hDynLib = NULL; -#if defined(HB_OS_WIN_32) if( hb_parclen( 1 ) > 0 ) { int argc = hb_pcount() - 1, i; @@ -97,47 +86,35 @@ HB_FUNC( HB_LIBLOAD ) { argv = ( char** ) hb_xgrab( sizeof( char* ) * argc ); for( i = 0; i < argc; ++i ) - { argv[i] = hb_parcx( i + 2 ); - } } - /* use stack address as first level marker */ - hb_vmBeginSymbolGroup( ( void * ) hb_stackId(), TRUE ); - hDynLib = ( void * ) LoadLibraryA( hb_parc( 1 ) ); - /* set real marker */ - hb_vmInitSymbolGroup( hDynLib, argc, argv ); - if( argv ) + if( hb_vmLockModuleSymbols() ) { - hb_xfree( argv ); - } - } -#elif defined(HB_OS_LINUX) && !defined(__WATCOMC__) - if( hb_parclen( 1 ) > 0 ) - { - int argc = hb_pcount() - 1, i; - char **argv = NULL; - - if( argc > 0 ) - { - argv = ( char** ) hb_xgrab( sizeof( char* ) * argc ); - for( i = 0; i < argc; ++i ) + /* use stack address as first level marker */ + hb_vmBeginSymbolGroup( ( void * ) hb_stackId(), TRUE ); +#if defined( HB_OS_WIN_32 ) + hDynLib = ( void * ) LoadLibraryA( hb_parc( 1 ) ); +#elif defined( HB_OS_OS2 ) { - argv[i] = hb_parcx( i + 2 ); + UCHAR LoadError[256] = ""; /* Area for load failure information */ + HMODULE hDynModule; + if( DosLoadModule( LoadError, sizeof( LoadError ), + hb_parc( 1 ), &hDynModule ) == NO_ERROR ) + hDynLib = ( void * ) hDynModule; } - } - - /* use stack address as first level marker */ - hb_vmBeginSymbolGroup( ( void * ) hb_stackId(), TRUE ); - hDynLib = ( void * ) dlopen( hb_parc( 1 ), RTLD_LAZY | RTLD_GLOBAL ); - /* set real marker */ - hb_vmInitSymbolGroup( hDynLib, argc, argv ); - if( argv ) - { - hb_xfree( argv ); - } - } +#elif defined( HB_OS_LINUX ) && !defined( __WATCOMC__ ) + hDynLib = ( void * ) dlopen( hb_parc( 1 ), RTLD_LAZY | RTLD_GLOBAL ); #endif + /* set real marker */ + hb_vmInitSymbolGroup( hDynLib, argc, argv ); + + hb_vmUnlockModuleSymbols(); + } + + if( argv ) + hb_xfree( argv ); + } if( hDynLib ) { @@ -151,28 +128,28 @@ HB_FUNC( HB_LIBLOAD ) HB_FUNC( HB_LIBFREE ) { -#if defined(HB_OS_WIN_32) - void * hDynLib = hb_parlib( 1 ); + BOOL fResult = FALSE; + void ** pDynLibPtr = ( void ** ) hb_parptrGC( hb_libRelease, 1 ); - if( hDynLib ) + if( pDynLibPtr && *pDynLibPtr && + hb_vmLockModuleSymbols() ) { - hb_vmExitSymbolGroup( hDynLib ); - hb_retl( FreeLibrary( ( HMODULE ) hDynLib ) ); - } - else -#elif defined(HB_OS_LINUX) && !defined(__WATCOMC__) - void * hDynLib = hb_parlib( 1 ); - - if( hDynLib ) - { - hb_vmExitSymbolGroup( hDynLib ); - hb_retl( dlclose( hDynLib ) == 0 ); - } - else + void * hDynLib = *pDynLibPtr; + if( hDynLib ) + { + *pDynLibPtr = NULL; + hb_vmExitSymbolGroup( hDynLib ); +#if defined( HB_OS_WIN_32 ) + fResult = FreeLibrary( ( HMODULE ) hDynLib ); +#elif defined( HB_OS_OS2 ) + fResult = DosFreeModule( ( HMODULE ) hDynLib ) == NO_ERROR; +#elif defined( HB_OS_LINUX ) && !defined (__WATCOMC__ ) + fResult = dlclose( hDynLib ) == 0; #endif - { - hb_retl( FALSE ); + } + hb_vmUnlockModuleSymbols(); } + hb_retl( FALSE ); } HB_FUNC( HB_LIBERROR ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 35dee4f544..a1f37fa74e 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -222,7 +222,9 @@ static void hb_vmMsgIndexReference( PHB_ITEM pRefer, PHB_ITEM pObject, PHB_IT #if defined( HB_MT_VM ) static int volatile hb_vmThreadRequest = 0; -static void hb_vmRequestTest( void ); +static void hb_vmRequestTest( void ); + +static PHB_ITEM s_pSymbolsMtx = NULL; static HB_CRITICAL_NEW( s_atInitMtx ); # define HB_ATINIT_LOCK hb_threadEnterCriticalSection( &s_atInitMtx ); @@ -853,6 +855,7 @@ HB_EXPORT void hb_vmInit( BOOL bStartMainProc ) #if defined( HB_MT_VM ) hb_threadInit(); hb_vmStackInit( hb_threadStateNew() ); /* initialize HVM thread stack */ + s_pSymbolsMtx = hb_threadMutexCreate( FALSE ); #else hb_stackInit(); /* initialize HVM stack */ #endif @@ -1053,6 +1056,11 @@ HB_EXPORT int hb_vmQuit( void ) #if defined( HB_MT_VM ) hb_vmStackRelease(); /* release HVM stack and remove it from linked HVM stacks list */ + if( s_pSymbolsMtx ) + { + hb_itemRelease( s_pSymbolsMtx ); + s_pSymbolsMtx = NULL; + } hb_threadExit(); #else hb_setRelease( hb_stackSetStruct() ); /* releases Sets */ @@ -6915,6 +6923,23 @@ PHB_SYMB hb_vmGetRealFuncSym( PHB_SYMB pSym ) return pSym; } +BOOL hb_vmLockModuleSymbols( void ) +{ +#if defined( HB_MT_VM ) + return !s_pSymbolsMtx || hb_threadMutexLock( s_pSymbolsMtx ); +#else + return TRUE; +#endif +} + +void hb_vmUnlockModuleSymbols( void ) +{ +#if defined( HB_MT_VM ) + if( s_pSymbolsMtx ) + hb_threadMutexUnlock( s_pSymbolsMtx ); +#endif +} + char * hb_vmFindModuleSymbolName( PHB_SYMB pSym ) { if( pSym ) @@ -7012,28 +7037,32 @@ void hb_vmFreeSymbols( PHB_SYMBOLS pSymbols ) { HB_TRACE(HB_TR_DEBUG, ("hb_vmFreeSymbols(%p)", pSymbols)); - if( pSymbols->fActive ) + if( pSymbols->fActive && hb_vmLockModuleSymbols() ) { - USHORT ui; - - for( ui = 0; ui < pSymbols->uiModuleSymbols; ++ui ) + if( pSymbols->fActive ) { - HB_SYMBOLSCOPE scope = pSymbols->pModuleSymbols[ ui ].scope.value & HB_FS_INITEXIT; + USHORT ui; - /* do not overwrite already initialized statics' frame */ - if( scope != HB_FS_INITEXIT ) + for( ui = 0; ui < pSymbols->uiModuleSymbols; ++ui ) { - PHB_SYMB pSymbol = &pSymbols->pModuleSymbols[ ui ]; - pSymbol->value.pFunPtr = NULL; - if( pSymbol->pDynSym && pSymbol->pDynSym->pSymbol != pSymbol && - ( pSymbol->scope.value & HB_FS_LOCAL ) == 0 ) - pSymbol->scope.value |= HB_FS_DEFERRED; + HB_SYMBOLSCOPE scope = pSymbols->pModuleSymbols[ ui ].scope.value & HB_FS_INITEXIT; + + /* do not overwrite already initialized statics' frame */ + if( scope != HB_FS_INITEXIT ) + { + PHB_SYMB pSymbol = &pSymbols->pModuleSymbols[ ui ]; + pSymbol->value.pFunPtr = NULL; + if( pSymbol->pDynSym && pSymbol->pDynSym->pSymbol != pSymbol && + ( pSymbol->scope.value & HB_FS_LOCAL ) == 0 ) + pSymbol->scope.value |= HB_FS_DEFERRED; + } + pSymbols->pModuleSymbols[ ui ].scope.value &= ~( HB_FS_PCODEFUNC | HB_FS_DYNCODE ); } - pSymbols->pModuleSymbols[ ui ].scope.value &= ~( HB_FS_PCODEFUNC | HB_FS_DYNCODE ); + pSymbols->hDynLib = NULL; + pSymbols->fActive = FALSE; + ++s_ulFreeSymbols; } - pSymbols->hDynLib = NULL; - pSymbols->fActive = FALSE; - ++s_ulFreeSymbols; + hb_vmUnlockModuleSymbols(); } } diff --git a/harbour/source/vm/runner.c b/harbour/source/vm/runner.c index 007d390f06..b9cfa47a17 100644 --- a/harbour/source/vm/runner.c +++ b/harbour/source/vm/runner.c @@ -468,27 +468,37 @@ static PHRB_BODY hb_hrbLoad( char* szHrbBody, ULONG ulBodySize ) } } - pHrbBody->pModuleSymbols = hb_vmRegisterSymbols( pHrbBody->pSymRead, - ( USHORT ) pHrbBody->ulSymbols, "pcode.hrb", 0, TRUE, FALSE ); - - if( pHrbBody->pModuleSymbols->pModuleSymbols != pSymRead ) + if( hb_vmLockModuleSymbols() ) { - /* - * Old unused symbol table has been recycled - free the one - * we allocated and disactivate static initialization [druzus] - */ - pHrbBody->pSymRead = pHrbBody->pModuleSymbols->pModuleSymbols; - hb_hrbFreeSymbols( pSymRead, pHrbBody->ulSymbols ); + pHrbBody->pModuleSymbols = hb_vmRegisterSymbols( pHrbBody->pSymRead, + ( USHORT ) pHrbBody->ulSymbols, "pcode.hrb", 0, TRUE, FALSE ); - pHrbBody->fInit = TRUE; + if( pHrbBody->pModuleSymbols->pModuleSymbols != pSymRead ) + { + /* + * Old unused symbol table has been recycled - free the one + * we allocated and disactivate static initialization [druzus] + */ + pHrbBody->pSymRead = pHrbBody->pModuleSymbols->pModuleSymbols; + hb_hrbFreeSymbols( pSymRead, pHrbBody->ulSymbols ); + + pHrbBody->fInit = TRUE; + } + else + { + /* mark symbol table as dynamically allocated so HVM will free it on exit */ + pHrbBody->pModuleSymbols->fAllocated = TRUE; + + /* initialize static variables */ + hb_hrbInitStatic( pHrbBody ); + } + hb_vmUnlockModuleSymbols(); } else { - /* mark symbol table as dynamically allocated so HVM will free it on exit */ - pHrbBody->pModuleSymbols->fAllocated = TRUE; - - /* initialize static variables */ - hb_hrbInitStatic( pHrbBody ); + hb_hrbFreeSymbols( pSymRead, pHrbBody->ulSymbols ); + hb_hrbUnLoad( pHrbBody ); + pHrbBody = NULL; } }