Esempio n. 1
0
PAL_ERROR
CorUnix::InternalCreateMutex(
    CPalThread *pthr,
    LPSECURITY_ATTRIBUTES lpMutexAttributes,
    BOOL bInitialOwner,
    LPCSTR lpName,
    HANDLE *phMutex
    )
{
    CObjectAttributes oa(nullptr, lpMutexAttributes);
    PAL_ERROR palError = NO_ERROR;
    IPalObject *pobjMutex = NULL;
    IPalObject *pobjRegisteredMutex = NULL;
    ISynchStateController *pssc = NULL;
    HANDLE hMutex = nullptr;

    _ASSERTE(NULL != pthr);
    _ASSERTE(NULL != phMutex);

    ENTRY("InternalCreateMutex(pthr=%p, lpMutexAttributes=%p, bInitialOwner=%d"
        ", lpName=%p, phMutex=%p)\n",
        pthr,
        lpMutexAttributes,
        bInitialOwner,
        lpName,
        phMutex
        );

    if (lpName != nullptr && lpName[0] == '\0')
    {
        // Empty name is treated as a request for an unnamed process-local mutex
        lpName = nullptr;
    }

    CObjectType *ot = lpName == nullptr ? &otMutex : &otNamedMutex;
    CAllowedObjectTypes *aot = lpName == nullptr ? &aotMutex : &aotNamedMutex;

    palError = g_pObjectManager->AllocateObject(
        pthr,
        ot,
        &oa,
        &pobjMutex
        );

    if (NO_ERROR != palError)
    {
        goto InternalCreateMutexExit;
    }

    if (lpName == nullptr)
    {
        palError = pobjMutex->GetSynchStateController(
            pthr,
            &pssc
            );

        if (NO_ERROR != palError)
        {
            ASSERT("Unable to create state controller (%d)\n", palError);
            goto InternalCreateMutexExit;
        }

        if (bInitialOwner)
        {
            palError = pssc->SetOwner(pthr);
        }
        else
        {
            palError = pssc->SetSignalCount(1);
        }

        pssc->ReleaseController();

        if (NO_ERROR != palError)
        {
            ASSERT("Unable to set initial mutex state (%d)\n", palError);
            goto InternalCreateMutexExit;
        }
    }

    palError = g_pObjectManager->RegisterObject(
        pthr,
        pobjMutex,
        aot,
        0, // should be MUTEX_ALL_ACCESS -- currently ignored (no Win32 security)
        &hMutex,
        &pobjRegisteredMutex
        );

    if (palError != NO_ERROR)
    {
        _ASSERTE(palError != ERROR_ALREADY_EXISTS); // PAL's naming infrastructure is not used for named mutexes
        _ASSERTE(pobjRegisteredMutex == nullptr);
        _ASSERTE(hMutex == nullptr);
        goto InternalCreateMutexExit;
    }

    // Now that the object has been registered successfully, it would have a reference associated with the handle, so release
    // the initial reference. Any errors from now on need to revoke the handle.
    _ASSERTE(pobjRegisteredMutex == pobjMutex);
    _ASSERTE(hMutex != nullptr);
    pobjMutex->ReleaseReference(pthr);
    pobjRegisteredMutex = nullptr;

    if (lpName != nullptr)
    {
        SharedMemoryProcessDataHeader *processDataHeader;
        bool created = false;
        try
        {
            processDataHeader = NamedMutexProcessData::CreateOrOpen(lpName, !!bInitialOwner, &created);
        }
        catch (SharedMemoryException ex)
        {
            palError = ex.GetErrorCode();
            goto InternalCreateMutexExit;
        }
        SharedMemoryProcessDataHeader::PalObject_SetProcessDataHeader(pobjMutex, processDataHeader);

        if (!created)
        {
            // Indicate to the caller that an existing mutex was opened, and hence the caller will not have initial ownership
            // of the mutex if requested through bInitialOwner
            palError = ERROR_ALREADY_EXISTS;
        }
    }

    *phMutex = hMutex;
    hMutex = nullptr;
    pobjMutex = nullptr;

InternalCreateMutexExit:

    _ASSERTE(pobjRegisteredMutex == nullptr);
    if (hMutex != nullptr)
    {
        g_pObjectManager->RevokeHandle(pthr, hMutex);
    }
    else if (NULL != pobjMutex)
    {
        pobjMutex->ReleaseReference(pthr);
    }

    LOGEXIT("InternalCreateMutex returns %i\n", palError);

    return palError;
}
Esempio n. 2
0
PAL_ERROR
CorUnix::InternalCreateMutex(
    CPalThread *pthr,
    LPSECURITY_ATTRIBUTES lpMutexAttributes,
    BOOL bInitialOwner,
    LPCWSTR lpName,
    HANDLE *phMutex
    )
{
    CObjectAttributes oa(lpName, lpMutexAttributes);
    PAL_ERROR palError = NO_ERROR;
    IPalObject *pobjMutex = NULL;
    IPalObject *pobjRegisteredMutex = NULL;
    ISynchStateController *pssc = NULL;

    _ASSERTE(NULL != pthr);
    _ASSERTE(NULL != phMutex);

    ENTRY("InternalCreateMutex(pthr=%p, lpMutexAttributes=%p, bInitialOwner=%d"
        ", lpName=%p, phMutex=%p)\n",
        pthr,
        lpMutexAttributes,
        bInitialOwner,
        lpName,
        phMutex
        );

    if (lpName != nullptr)
    {
        ASSERT("lpName: Cross-process named objects are not supported in PAL");
        palError = ERROR_NOT_SUPPORTED;
        goto InternalCreateMutexExit;
    }

    palError = g_pObjectManager->AllocateObject(
        pthr,
        &otMutex,
        &oa,
        &pobjMutex
        );

    if (NO_ERROR != palError)
    {
        goto InternalCreateMutexExit;
    }

    palError = pobjMutex->GetSynchStateController(
        pthr,
        &pssc
        );

    if (NO_ERROR != palError)
    {
        ASSERT("Unable to create state controller (%d)\n", palError);
        goto InternalCreateMutexExit;
    }

    if (bInitialOwner)
    {
        palError = pssc->SetOwner(pthr);
    }
    else
    {
        palError = pssc->SetSignalCount(1);
    }

    pssc->ReleaseController();

    if (NO_ERROR != palError)
    {
        ASSERT("Unable to set initial mutex state (%d)\n", palError);
        goto InternalCreateMutexExit;
    }

    palError = g_pObjectManager->RegisterObject(
        pthr,
        pobjMutex,
        &aotMutex, 
        0, // should be MUTEX_ALL_ACCESS -- currently ignored (no Win32 security)
        phMutex,
        &pobjRegisteredMutex
        );

    //
    // pobjMutex is invalidated by the call to RegisterObject, so NULL it
    // out here to ensure that we don't try to release a reference on
    // it down the line.
    //
    
    pobjMutex = NULL;

InternalCreateMutexExit:

    if (NULL != pobjMutex)
    {
        pobjMutex->ReleaseReference(pthr);
    }

    if (NULL != pobjRegisteredMutex)
    {
        pobjRegisteredMutex->ReleaseReference(pthr);
    }

    LOGEXIT("InternalCreateMutex returns %i\n", palError);

    return palError;
}