Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Jason Goepel

Member Since 15 May 2013
Offline Last Active Yesterday, 07:53 AM

Posts I've Made

In Topic: "Null pointer access" putting object type in exception info

02 April 2015 - 08:26 AM

I'm going to try and hack something together.  My immediate purpose may be satisfied by adding more exception information when the exception is set within "CallSystemFunction."  I'll let you know if I come up with anything clever.


In Topic: asBEHAVE_REF_CAST / asBEHAVE_IMPLICIT_REF_CAST deprecated...

03 February 2015 - 07:36 AM

asBEHAVE_REF_CAST             ==>  opCast

asBEHAVE_IMPLICIT_REF_CAST    ==>  opImplCast

asBEHAVE_VALUE_CAST           ==>  opConv

asBEHAVE_IMPLICIT_VALUE_CAST  ==>  opImplConv


In Topic: Multithreading - Creating a Module

11 December 2014 - 11:53 AM

Thanks for the quick response, but I think there may still be a slight issue.  It seems like if two threads enter this block:

ACQUIRESHARED(engineRWLock);
if( lastModule && lastModule->name == name )
    retModule = lastModule;
else
{
    // TODO: optimize: Improve linear search
    for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
        if( scriptModules[n] && scriptModules[n]->name == name )
        {
            lastModule = retModule = scriptModules[n];
            break;
        }
}
RELEASESHARED(engineRWLock);

 

Then there is the opportunity for:

Thread1:  "lastModule->name == name"    true

Thread2:  "scriptModules[n]->name == name"  true

Thread2:  "lastModule = retModule = scriptModules[n]"

Thread1:  "retModule = lastModule"

 

If that were to happen, then Thread1 would return the incorrect module.  It seems like "lastModule" should always be within an exclusive lock when being written to.


In Topic: Multithreading - Creating a Module

10 December 2014 - 07:42 AM

Sorry.  I thought I had uploaded it.


In Topic: Multithreading - Creating a Module

09 December 2014 - 01:00 PM

I think I found a gap in your solution.

asCModule *asCScriptEngine::GetModule(const char *_name, bool create)
{
    // Accept null as well as zero-length string
    const char *name = "";
    if( _name != 0 ) name = _name;

    if( lastModule && lastModule->name == name )
        return lastModule;

    lastModule = 0;
    ACQUIRESHARED(engineRWLock);
    // TODO: optimize: Improve linear search
    for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
        if( scriptModules[n] && scriptModules[n]->name == name )
        {
            lastModule = scriptModules[n];
            break;
        }
    RELEASESHARED(engineRWLock);
    if( lastModule ) 
        return lastModule;

    if( create )
    {
        asCModule *module = asNEW(asCModule)(name, this);
        if( module == 0 )
        {
            // Out of memory
            return 0;
        }

        ACQUIREEXCLUSIVE(engineRWLock);
        scriptModules.PushLast(module);
        RELEASEEXCLUSIVE(engineRWLock);

        lastModule = module;

        return lastModule;
    }

    return 0;
}

The member variable "lastModule" should be guarded under an exclusive lock when writing.  I had one user experience a crash from a module being destroyed twice.  The problem was two threads were attempting to create new modules simultaneously.  One of the threads searched through the "scriptModules" array an found no matching module, while the other thread created a new module and saved it to "lastModule".  Then the first thread tested "lastModule" (immediately after the search), and it was not null (even though the search was not successful).  So both function calls returns the same "asIModule" pointer, setting the stage for the crash.

 

I have attached a patch with my solution.

 


PARTNERS