//returns true if process exited
        bool wait_for_pid(ProcessId pid, bool block=true, int* exit_code=NULL) {
#ifdef _WIN32
            verify(registry._handles.count(pid));
            HANDLE h = registry._handles[pid];

            if (block)
                WaitForSingleObject(h, INFINITE);

            DWORD tmp;
            if(GetExitCodeProcess(h, &tmp)) {
                if ( tmp == STILL_ACTIVE ) {
                    return false;
                }
                CloseHandle(h);
                registry._handles.erase(pid);
                if (exit_code)
                    *exit_code = tmp;
                return true;
            }
            else {
                return false;
            }
#else
            int tmp;
            bool ret = (pid.toNative() == waitpid(pid.toNative(), &tmp, (block ? 0 : WNOHANG)));
            if (exit_code)
                *exit_code = WEXITSTATUS(tmp);
            return ret;

#endif
        }
Beispiel #2
0
// returns true if process exited
// If this function returns true, it will always call `registry.unregisterProgram(pid);`
// If block is true, this will throw if it cannot wait for the processes to exit.
bool wait_for_pid(ProcessId pid, bool block = true, int* exit_code = NULL) {
#ifdef _WIN32
    verify(registry.countHandleForPid(pid));
    HANDLE h = registry.getHandleForPid(pid);

    // wait until the process object is signaled before getting its
    // exit code. do this even when block is false to ensure that all
    // file handles open in the process have been closed.

    DWORD ret = WaitForSingleObject(h, (block ? INFINITE : 0));
    if (ret == WAIT_TIMEOUT) {
        return false;
    } else if (ret != WAIT_OBJECT_0) {
        const auto ewd = errnoWithDescription();
        log() << "wait_for_pid: WaitForSingleObject failed: " << ewd;
    }

    DWORD tmp;
    if (GetExitCodeProcess(h, &tmp)) {
        if (tmp == STILL_ACTIVE) {
            uassert(
                ErrorCodes::UnknownError, "Process is STILL_ACTIVE even after blocking", !block);
            return false;
        }
        CloseHandle(h);
        registry.eraseHandleForPid(pid);
        if (exit_code)
            *exit_code = tmp;

        registry.unregisterProgram(pid);
        return true;
    } else {
        const auto ewd = errnoWithDescription();
        log() << "GetExitCodeProcess failed: " << ewd;
        return false;
    }
#else
    int tmp;
    int ret;
    do {
        ret = waitpid(pid.toNative(), &tmp, (block ? 0 : WNOHANG));
    } while (ret == -1 && errno == EINTR);
    if (ret && exit_code) {
        if (WIFEXITED(tmp)) {
            *exit_code = WEXITSTATUS(tmp);
        } else if (WIFSIGNALED(tmp)) {
            *exit_code = -WTERMSIG(tmp);
        } else {
            MONGO_UNREACHABLE;
        }
    }
    if (ret) {
        registry.unregisterProgram(pid);
    } else if (block) {
        uasserted(ErrorCodes::UnknownError, "Process did not exit after blocking");
    }
    return ret == pid.toNative();
#endif
}
// returns true if process exited
bool wait_for_pid(ProcessId pid, bool block = true, int* exit_code = NULL) {
#ifdef _WIN32
    verify(registry._handles.count(pid));
    HANDLE h = registry._handles[pid];

    if (block) {
        if (WaitForSingleObject(h, INFINITE)) {
            log() << "WaitForSingleObject failed: " << errnoWithDescription();
        }
    }

    DWORD tmp;
    if (GetExitCodeProcess(h, &tmp)) {
        if (tmp == STILL_ACTIVE) {
            if (block)
                log() << "Process is STILL_ACTIVE even after blocking";
            return false;
        }
        CloseHandle(h);
        registry._handles.erase(pid);
        if (exit_code)
            *exit_code = tmp;
        return true;
    } else {
        log() << "GetExitCodeProcess failed: " << errnoWithDescription();
        return false;
    }
#else
    int tmp;
    bool ret = (pid.toNative() == waitpid(pid.toNative(), &tmp, (block ? 0 : WNOHANG)));
    if (ret && exit_code) {
        if (WIFEXITED(tmp)) {
            *exit_code = WEXITSTATUS(tmp);
        } else if (WIFSIGNALED(tmp)) {
            *exit_code = -WTERMSIG(tmp);
        } else {
            MONGO_UNREACHABLE;
        }
    }
    return ret;

#endif
}
      inline void kill_wrapper( ProcessId pid, int sig, int port, const BSONObj& opt ) {
#ifdef _WIN32
            if (sig == SIGKILL || port == 0) {
                verify( registry._handles.count(pid) );
                TerminateProcess(registry._handles[pid], 1); // returns failure for "zombie" processes.
                return;
            }

            std::string eventName = getShutdownSignalName(pid.asUInt32());

            HANDLE event = OpenEventA(EVENT_MODIFY_STATE, FALSE, eventName.c_str());
            if (event == NULL) {
                int gle = GetLastError();
                if (gle != ERROR_FILE_NOT_FOUND) {
                    warning() << "kill_wrapper OpenEvent failed: " << errnoWithDescription();
                }
                else {
                    log() << "kill_wrapper OpenEvent failed to open event to the process "
                        << pid.asUInt32() << ". It has likely died already";
                }
                return;
            }

            ON_BLOCK_EXIT(CloseHandle, event);

            bool result = SetEvent(event);
            if (!result) {
                error() << "kill_wrapper SetEvent failed: " << errnoWithDescription();
                return;
            }
#else
            int x = kill( pid.toNative(), sig );
            if ( x ) {
                if ( errno == ESRCH ) {
                }
                else {
                    log() << "killFailed: " << errnoWithDescription() << endl;
                    verify( x == 0 );
                }
            }

#endif
        }
Beispiel #5
0
      inline void kill_wrapper( ProcessId pid, int sig, int port, const BSONObj& opt ) {
#ifdef _WIN32
            if (sig == SIGKILL || port == 0) {
                verify( registry._handles.count(pid) );
                TerminateProcess(registry._handles[pid], 1); // returns failure for "zombie" processes.
                return;
            }

            std::string eventName = getShutdownSignalName(pid.asUInt32());

            HANDLE event = OpenEventA(EVENT_MODIFY_STATE, FALSE, eventName.c_str());
            if (event == NULL) {
                int gle = GetLastError();
                if (gle != ERROR_FILE_NOT_FOUND) {
                    warning() << "kill_wrapper OpenEvent failed: " << errnoWithDescription();
                }
                else {
                    log() << "kill_wrapper OpenEvent failed to open event to the process "
                        << pid.asUInt32()
                        << ". It has likely died already or server is running an older version."
                        << " Attempting to shutdown through admin command.";

                    // Back-off to the old way of shutting down the server on Windows, in case we
                    // are managing a pre-2.6.0rc0 service, which did not have the event.
                    //
                    try {
                        DBClientConnection conn;
                        conn.connect("127.0.0.1:" + BSONObjBuilder::numStr(port));

                        BSONElement authObj = opt["auth"];

                        if (!authObj.eoo()){
                            string errMsg;
                            conn.auth("admin", authObj["user"].String(),
                                authObj["pwd"].String(), errMsg);

                            if (!errMsg.empty()) {
                                cout << "Failed to authenticate before shutdown: "
                                    << errMsg << endl;
                            }
                        }

                        BSONObj info;
                        BSONObjBuilder b;
                        b.append("shutdown", 1);
                        b.append("force", 1);
                        conn.runCommand("admin", b.done(), info);
                    }
                    catch (...) {
                        // Do nothing. This command never returns data to the client and the driver
                        // doesn't like that.
                        //
                    }
                }
                return;
            }

            ON_BLOCK_EXIT(CloseHandle, event);

            bool result = SetEvent(event);
            if (!result) {
                error() << "kill_wrapper SetEvent failed: " << errnoWithDescription();
                return;
            }
#else
            int x = kill( pid.toNative(), sig );
            if ( x ) {
                if ( errno == ESRCH ) {
                }
                else {
                    log() << "killFailed: " << errnoWithDescription() << endl;
                    verify( x == 0 );
                }
            }

#endif
        }