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.
This commit is contained in:
Przemyslaw Czerpak
2008-10-13 18:21:42 +00:00
parent 52b81aace8
commit b9e2e7b6f0
6 changed files with 152 additions and 99 deletions

View File

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

View File

@@ -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[] );

View File

@@ -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 );

View File

@@ -67,27 +67,16 @@
# include <dlfcn.h>
#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 )

View File

@@ -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();
}
}

View File

@@ -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;
}
}