Ejemplo n.º 1
0
LONG(CALLBACK win_exception_handler)(LPEXCEPTION_POINTERS ep) {

    HMODULE hm;
    MODULEINFO mi;
    WCHAR fn[MAX_PATH];
    char message[512];
    unsigned int code;

    code = ep->ExceptionRecord->ExceptionCode;

    GetModuleHandleEx(
        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)(ep->ExceptionRecord->ExceptionAddress), &hm );
    GetModuleInformation(GetCurrentProcess(), hm, &mi, sizeof(mi) );
    GetModuleFileNameEx(GetCurrentProcess(), hm, fn, MAX_PATH );

    sprintf(message, "SE %s at address %p inside %s loaded at base address %p\n",
        seDescription(code), ep->ExceptionRecord->ExceptionAddress, fn,
        mi.lpBaseOfDll);

    if(code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_IN_PAGE_ERROR ) {
        sprintf("%sInvalid operation: %s at address %p\n", message,
            opDescription(ep->ExceptionRecord->ExceptionInformation[0]),
            ep->ExceptionRecord->ExceptionInformation[1]);
    }

    if(code == EXCEPTION_IN_PAGE_ERROR) {
        sprintf("%sUnderlying NTSTATUS code that resulted in the exception %i", message,
            ep->ExceptionRecord->ExceptionInformation[2]);
    }

    Native_Exception.reason = message;

    SetUnhandledExceptionFilter(win_exception_handler);

    Except_raise(&Native_Exception, "", 0);
    return 0;
}
StatusWith<SharedSemiFuture<ReplIndexBuildState::IndexCatalogStats>>
IndexBuildsCoordinatorMongod::startIndexBuild(OperationContext* opCtx,
                                              CollectionUUID collectionUUID,
                                              const std::vector<BSONObj>& specs,
                                              const UUID& buildUUID) {
    std::vector<std::string> indexNames;
    for (auto& spec : specs) {
        std::string name = spec.getStringField(IndexDescriptor::kIndexNameFieldName);
        if (name.empty()) {
            return Status(
                ErrorCodes::CannotCreateIndex,
                str::stream() << "Cannot create an index for a spec '" << spec
                              << "' without a non-empty string value for the 'name' field");
        }
        indexNames.push_back(name);
    }

    auto nss = UUIDCatalog::get(opCtx).lookupNSSByUUID(collectionUUID);
    auto dbName = nss.db().toString();
    auto replIndexBuildState =
        std::make_shared<ReplIndexBuildState>(buildUUID, collectionUUID, dbName, indexNames, specs);

    Status status = _registerIndexBuild(opCtx, replIndexBuildState);
    if (!status.isOK()) {
        return status;
    }

    // Run index build in-line if we are transitioning between replication modes.
    // While the RSTLExclusive is being held, the async thread in the thread pool is not allowed
    // to take locks.
    if (opCtx->lockState()->isRSTLExclusive()) {
        log() << "Running index build on current thread because we are transitioning between "
                 "replication states: "
              << buildUUID;
        // Sets up and runs the index build. Sets result and cleans up index build.
        _runIndexBuild(opCtx, buildUUID);
        return replIndexBuildState->sharedPromise.getFuture();
    }

    // Task in thread pool should retain the caller's deadline.
    auto deadline = opCtx->getDeadline();
    auto timeoutError = opCtx->getTimeoutError();

    // Task in thread pool should have similar CurOp representation to the caller so that it can be
    // identified as a createIndexes operation.
    BSONObj opDesc;
    {
        stdx::unique_lock<Client> lk(*opCtx->getClient());
        auto curOp = CurOp::get(opCtx);
        opDesc = curOp->opDescription().getOwned();
    }

    status = _threadPool.schedule([ this, buildUUID, deadline, timeoutError, opDesc ]() noexcept {
        auto opCtx = Client::getCurrent()->makeOperationContext();

        opCtx->setDeadlineByDate(deadline, timeoutError);

        {
            stdx::unique_lock<Client> lk(*opCtx->getClient());
            auto curOp = CurOp::get(opCtx.get());
            curOp->setOpDescription_inlock(opDesc);
        }

        // Sets up and runs the index build. Sets result and cleans up index build.
        _runIndexBuild(opCtx.get(), buildUUID);
    });

    // Clean up the index build if we failed to schedule it.
    if (!status.isOK()) {
        stdx::unique_lock<stdx::mutex> lk(_mutex);

        // Unregister the index build before setting the promises, so callers do not see the build
        // again.
        _unregisterIndexBuild(lk, opCtx, replIndexBuildState);

        // Set the promise in case another thread already joined the index build.
        replIndexBuildState->sharedPromise.setError(status);

        return status;
    }

    return replIndexBuildState->sharedPromise.getFuture();
}