예제 #1
0
void ForkedBroker::kill(int sig) {
    if (pid == 0) return;
    int savePid = pid;
    pid = 0;                // Reset pid here in case of an exception.
    using qpid::ErrnoException;
    if (::kill(savePid, sig) < 0)
            throw ErrnoException("kill failed");
    int status;
    if (::waitpid(savePid, &status, 0) < 0 && sig != 9)
        throw ErrnoException("wait for forked process failed");
    if (WEXITSTATUS(status) != 0 && sig != 9)
        throw qpid::Exception(QPID_MSG("Forked broker exited with: " << WEXITSTATUS(status)));
}
예제 #2
0
void ForkedBroker::init(const Args& userArgs) {
    using qpid::ErrnoException;
    port = 0;
    int pipeFds[2];
    if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe");

    // Ignore the SIGCHLD signal generated by an exitting child
    // We will clean up any exitting children in the waitpid above
    // This should really be neater (like only once not per fork)
    struct ::sigaction sa;
    sa.sa_handler = ignore_signal;
    ::sigemptyset(&sa.sa_mask);
    ::sigaddset(&sa.sa_mask, SIGCHLD);
    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
    ::sigaction(SIGCHLD, &sa, 0);

    pid = ::fork();
    if (pid < 0) throw ErrnoException("Fork failed");
    if (pid) {              // parent
        ::close(pipeFds[1]);
        FILE* f = ::fdopen(pipeFds[0], "r");
        if (!f) throw ErrnoException("fopen failed");
        if (::fscanf(f, "%d", &port) != 1) {
            if (ferror(f)) throw ErrnoException("Error reading port number from child.");
            else throw qpid::Exception("EOF reading port number from child.");
        }
        ::fclose(f);
	running = true;
    }
    else {                  // child
        ::close(pipeFds[0]);
        int fd = ::dup2(pipeFds[1], 1); // pipe stdout to the parent.
        if (fd < 0) throw ErrnoException("dup2 failed");
        const char* prog = ::getenv("QPIDD_EXEC");
        if (!prog) prog = "../qpidd"; // This only works from within svn checkout
        Args args(userArgs);
        args.push_back("--port=0");
        // Keep quiet except for errors.
        if (!::getenv("QPID_TRACE") && !::getenv("QPID_LOG_ENABLE")
            && find_if(userArgs.begin(), userArgs.end(), isLogOption) == userArgs.end())
            args.push_back("--log-enable=error+");
        std::vector<const char*> argv(args.size());
        std::transform(args.begin(), args.end(), argv.begin(), boost::bind(&std::string::c_str, _1));
        argv.push_back(0);
        QPID_LOG(debug, "ForkedBroker exec " << prog << ": " << args);

        execv(prog, const_cast<char* const*>(&argv[0]));
        QPID_LOG(critical, "execv failed to start broker: prog=\"" << prog << "\"; args=\"" << args << "\"; errno=" << errno << " (" << std::strerror(errno) << ")");
        ::exit(1);
    }
}
예제 #3
0
파일: DtxManager.cpp 프로젝트: ncdc/qpid
DtxWorkRecord* DtxManager::getWork(const std::string& xid)
{
    Mutex::ScopedLock locker(lock);
    WorkMap::iterator i = work.find(xid);
    if (i == work.end()) {
        throw NotFoundException(QPID_MSG("Unrecognised xid " << convert(xid)));
    }
    return ptr_map_ptr(i);
}
예제 #4
0
파일: DtxManager.cpp 프로젝트: ncdc/qpid
DtxWorkRecord* DtxManager::createWork(const std::string& xid)
{
    Mutex::ScopedLock locker(lock);
    WorkMap::iterator i = work.find(xid);
    if (i != work.end()) {
        throw NotAllowedException(QPID_MSG("Xid " << convert(xid) << " is already known (use 'join' to add work to an existing xid)"));
    } else {
        std::string ncxid = xid; // Work around const correctness problems in ptr_map.
        return ptr_map_ptr(work.insert(ncxid, new DtxWorkRecord(ncxid, store)).first);
    }
}
예제 #5
0
파일: DtxManager.cpp 프로젝트: ncdc/qpid
void DtxManager::timedout(const std::string& xid)
{
    Mutex::ScopedLock locker(lock);
    WorkMap::iterator i = work.find(xid);
    if (i == work.end()) {
        QPID_LOG(warning, "Transaction timeout failed: no record for xid");
    } else {
        ptr_map_ptr(i)->timedout();
        //TODO: do we want to have a timed task to cleanup, or can we rely on an explicit completion?
        //timer->add(new DtxCleanup(60*30/*30 mins*/, boost::bind(&DtxManager::remove, this, xid)));
    }
}
예제 #6
0
void ForkedBroker::init(const Args& userArgs) {
    using qpid::ErrnoException;
    port = 0;
    int pipeFds[2];
    if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe");
    pid = ::fork();
    if (pid < 0) throw ErrnoException("Fork failed");
    if (pid) {              // parent
        ::close(pipeFds[1]);
        FILE* f = ::fdopen(pipeFds[0], "r");
        if (!f) throw ErrnoException("fopen failed");
        if (::fscanf(f, "%d", &port) != 1) {
            if (ferror(f)) throw ErrnoException("Error reading port number from child.");
            else throw qpid::Exception("EOF reading port number from child.");
        }
        ::close(pipeFds[0]);
    }
    else {                  // child
        ::close(pipeFds[0]);
        int fd = ::dup2(pipeFds[1], 1); // pipe stdout to the parent.
        if (fd < 0) throw ErrnoException("dup2 failed");
        const char* prog = ::getenv("QPIDD_EXEC");
        if (!prog) prog = "../qpidd"; // This only works from within svn checkout
        Args args(userArgs);
        args.push_back("--port=0");
        // Keep quiet except for errors.
        if (!::getenv("QPID_TRACE") && !::getenv("QPID_LOG_ENABLE")
            && find_if(userArgs.begin(), userArgs.end(), isLogOption) == userArgs.end())
            args.push_back("--log-enable=error+");
        std::vector<const char*> argv(args.size());
        std::transform(args.begin(), args.end(), argv.begin(), boost::bind(&std::string::c_str, _1));
        argv.push_back(0);
        QPID_LOG(debug, "ForkedBroker exec " << prog << ": " << args);
        execv(prog, const_cast<char* const*>(&argv[0]));
        QPID_LOG(critical, "execv failed to start broker: prog=\"" << prog << "\"; args=\"" << args << "\"; errno=" << errno << " (" << std::strerror(errno) << ")");
        ::exit(1);
    }
}