Пример #1
0
            void launch_process(int child_stdout){
#ifdef _WIN32
                stringstream ss;
                for( unsigned i=0; i < argv_.size(); i++ ){
                    if (i) ss << ' ';
                    if (argv_[i].find(' ') == string::npos)
                        ss << argv_[i];
                    else
                        ss << '"' << argv_[i] << '"';
                }

                string args = ss.str();
                
                boost::scoped_array<TCHAR> args_tchar (new TCHAR[args.size() + 1]);
                size_t i;
                for(i=0; i < args.size(); i++)
                    args_tchar[i] = args[i];
                args_tchar[i] = 0;

                HANDLE h = (HANDLE)_get_osfhandle(child_stdout);
                assert(h != INVALID_HANDLE_VALUE);
                assert(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 1));

                STARTUPINFO si;
                ZeroMemory(&si, sizeof(si));
                si.cb = sizeof(si);
                si.hStdError = h;
                si.hStdOutput = h;
                si.dwFlags |= STARTF_USESTDHANDLES;

                PROCESS_INFORMATION pi;
                ZeroMemory(&pi, sizeof(pi));

                bool success = CreateProcess( NULL, args_tchar.get(), NULL, NULL, true, 0, NULL, NULL, &si, &pi) != 0;
                {
                    stringstream ss;
                    ss << "couldn't start process " << argv_[0];
                    uassert(13294, ss.str(), success);
                }

                CloseHandle(pi.hThread);

                pid_ = pi.dwProcessId;
                handles.insert( make_pair( pid_, pi.hProcess ) );
                
#else

                pid_ = fork();
                assert( pid_ != -1 );
                
                if ( pid_ == 0 ) {
                    // DON'T ASSERT IN THIS BLOCK - very bad things will happen

                    const char** argv = new const char* [argv_.size()+1]; // don't need to free - in child
                    for (unsigned i=0; i < argv_.size(); i++){
                        argv[i] = argv_[i].c_str();
                    }
                    argv[argv_.size()] = 0;
                    
                    if ( dup2( child_stdout, STDOUT_FILENO ) == -1 ||
                         dup2( child_stdout, STDERR_FILENO ) == -1 )
                    {
                        cout << "Unable to dup2 child output: " << errnoWithDescription() << endl;
                        ::_Exit(-1); //do not pass go, do not call atexit handlers
                    }

                    const char** env = new const char* [2]; // don't need to free - in child
                    env[0] = NULL;
#if defined(HEAP_CHECKING)
                    env[0] = "HEAPCHECK=normal";
                    env[1] = NULL;

                    // Heap-check for mongos only. 'argv[0]' must be in the path format.
                    if ( argv_[0].find("mongos") != string::npos){
                        execvpe( argv[ 0 ], const_cast<char**>(argv) , const_cast<char**>(env) );
                    }
#endif // HEAP_CHECKING

                    execvp( argv[ 0 ], const_cast<char**>(argv) );

                    cout << "Unable to start program " << argv[0] << ' ' << errnoWithDescription() << endl;
                    ::_Exit(-1);
                }

#endif
            }
Пример #2
0
        void ProgramRunner::launchProcess( int child_stdout ) {
#ifdef _WIN32
            stringstream ss;
            for( unsigned i=0; i < _argv.size(); i++ ) {
                if (i) ss << ' ';
                if (_argv[i].find(' ') == string::npos)
                    ss << _argv[i];
                else {
                    ss << '"';
                    // escape all embedded quotes
                    for (size_t j=0; j<_argv[i].size(); ++j) {
                        if (_argv[i][j]=='"') ss << '\\';
                        ss << _argv[i][j];
                    }
                    ss << '"';
                }
            }

            string args = ss.str();

            boost::scoped_array<TCHAR> args_tchar (new TCHAR[args.size() + 1]);
            size_t i;
            for(i=0; i < args.size(); i++)
                args_tchar[i] = args[i];
            args_tchar[i] = 0;

            HANDLE h = (HANDLE)_get_osfhandle(child_stdout);
            verify(h != INVALID_HANDLE_VALUE);
            verify(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 1));

            STARTUPINFO si;
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);
            si.hStdError = h;
            si.hStdOutput = h;
            si.dwFlags |= STARTF_USESTDHANDLES;

            PROCESS_INFORMATION pi;
            ZeroMemory(&pi, sizeof(pi));

            bool success = CreateProcess( NULL, args_tchar.get(), NULL, NULL, true, 0, NULL, NULL, &si, &pi) != 0;
            if (!success) {
                LPSTR lpMsgBuf=0;
                DWORD dw = GetLastError();
                FormatMessageA(
                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,
                    dw,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    (LPSTR)&lpMsgBuf,
                    0, NULL );
                stringstream ss;
                ss << "couldn't start process " << _argv[0] << "; " << lpMsgBuf;
                uassert(14042, ss.str(), success);
                LocalFree(lpMsgBuf);
            }

            CloseHandle(pi.hThread);

            _pid = ProcessId::fromNative(pi.dwProcessId);
            registry._handles.insert( make_pair( _pid, pi.hProcess ) );

#else

            scoped_array<const char *> argvStorage( new const char* [_argv.size()+1] );
            const char** argv = argvStorage.get();
            for (unsigned i=0; i < _argv.size(); i++) {
                argv[i] = _argv[i].c_str();
            }
            argv[_argv.size()] = 0;

            scoped_array<const char *> envStorage( new const char* [2] );
            const char** env = envStorage.get();
            env[0] = NULL;
            env[1] = NULL;

            pid_t nativePid = fork();
            _pid = ProcessId::fromNative(nativePid);
            // Async signal unsafe functions should not be called in the child process.

            verify( nativePid != -1 );
            if ( nativePid == 0 ) {
                // DON'T ASSERT IN THIS BLOCK - very bad things will happen

                if ( dup2( child_stdout, STDOUT_FILENO ) == -1 ||
                        dup2( child_stdout, STDERR_FILENO ) == -1 ) {

                    // Async signal unsafe code reporting a terminal error condition.
                    cout << "Unable to dup2 child output: " << errnoWithDescription() << endl;
                    quickExit(-1); //do not pass go, do not call atexit handlers
                }

                // NOTE execve is async signal safe, but it is not clear that execvp is async
                // signal safe.
                execvp( argv[ 0 ], const_cast<char**>(argv) );

                // Async signal unsafe code reporting a terminal error condition.
                cout << "Unable to start program " << argv[0] << ' ' << errnoWithDescription() << endl;
                quickExit(-1);
            }

#endif
        }
Пример #3
0
            void launch_process(int child_stdout) {
#ifdef _WIN32
                stringstream ss;
                for( unsigned i=0; i < argv_.size(); i++ ) {
                    if (i) ss << ' ';
                    if (argv_[i].find(' ') == string::npos)
                        ss << argv_[i];
                    else {
                        ss << '"';
                        // escape all embedded quotes
                        for (size_t j=0; j<argv_[i].size(); ++j) {
                            if (argv_[i][j]=='"') ss << '"';
                            ss << argv_[i][j];
                        }
                        ss << '"';
                    }
                }

                string args = ss.str();

                boost::scoped_array<TCHAR> args_tchar (new TCHAR[args.size() + 1]);
                size_t i;
                for(i=0; i < args.size(); i++)
                    args_tchar[i] = args[i];
                args_tchar[i] = 0;

                HANDLE h = (HANDLE)_get_osfhandle(child_stdout);
                assert(h != INVALID_HANDLE_VALUE);
                assert(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 1));

                STARTUPINFO si;
                ZeroMemory(&si, sizeof(si));
                si.cb = sizeof(si);
                si.hStdError = h;
                si.hStdOutput = h;
                si.dwFlags |= STARTF_USESTDHANDLES;

                PROCESS_INFORMATION pi;
                ZeroMemory(&pi, sizeof(pi));

                bool success = CreateProcess( NULL, args_tchar.get(), NULL, NULL, true, 0, NULL, NULL, &si, &pi) != 0;
                if (!success) {
                    LPSTR lpMsgBuf=0;
                    DWORD dw = GetLastError();
                    FormatMessageA(
                        FORMAT_MESSAGE_ALLOCATE_BUFFER |
                        FORMAT_MESSAGE_FROM_SYSTEM |
                        FORMAT_MESSAGE_IGNORE_INSERTS,
                        NULL,
                        dw,
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        (LPSTR)&lpMsgBuf,
                        0, NULL );
                    stringstream ss;
                    ss << "couldn't start process " << argv_[0] << "; " << lpMsgBuf;
                    uassert(14042, ss.str(), success);
                    LocalFree(lpMsgBuf);
                }

                CloseHandle(pi.hThread);

                pid_ = pi.dwProcessId;
                handles.insert( make_pair( pid_, pi.hProcess ) );

#else

                pid_ = fork();
                assert( pid_ != -1 );

                if ( pid_ == 0 ) {
                    // DON'T ASSERT IN THIS BLOCK - very bad things will happen

                    const char** argv = new const char* [argv_.size()+1]; // don't need to free - in child
                    for (unsigned i=0; i < argv_.size(); i++) {
                        argv[i] = argv_[i].c_str();
                    }
                    argv[argv_.size()] = 0;

                    if ( dup2( child_stdout, STDOUT_FILENO ) == -1 ||
                            dup2( child_stdout, STDERR_FILENO ) == -1 ) {
                        cout << "Unable to dup2 child output: " << errnoWithDescription() << endl;
                        ::_Exit(-1); //do not pass go, do not call atexit handlers
                    }

                    const char** env = new const char* [2]; // don't need to free - in child
                    env[0] = NULL;
#if defined(HEAP_CHECKING)
                    env[0] = "HEAPCHECK=normal";
                    env[1] = NULL;

                    // Heap-check for mongos only. 'argv[0]' must be in the path format.
                    if ( argv_[0].find("mongos") != string::npos) {
                        execvpe( argv[ 0 ], const_cast<char**>(argv) , const_cast<char**>(env) );
                    }
#endif // HEAP_CHECKING

                    execvp( argv[ 0 ], const_cast<char**>(argv) );

                    cout << "Unable to start program " << argv[0] << ' ' << errnoWithDescription() << endl;
                    ::_Exit(-1);
                }

#endif
            }