summaryrefslogtreecommitdiff
path: root/src/mongo/shell/shell_utils_launcher.cpp
diff options
context:
space:
mode:
authorApollon Oikonomopoulos <apoikos@debian.org>2016-01-14 00:10:06 +0200
committerApollon Oikonomopoulos <apollon@skroutz.gr>2016-01-14 00:10:06 +0200
commit374e1947abcd3e127a2a613aff73ecffdb9199ea (patch)
treed83973c3c9802450acd5b5e86fe0d4e8e60a3a1b /src/mongo/shell/shell_utils_launcher.cpp
parent65585c90b12d6523bea75a2aebaae2a2fdf9e641 (diff)
Imported Upstream version 2.6.11upstream/2.6.11
Diffstat (limited to 'src/mongo/shell/shell_utils_launcher.cpp')
-rw-r--r--src/mongo/shell/shell_utils_launcher.cpp167
1 files changed, 101 insertions, 66 deletions
diff --git a/src/mongo/shell/shell_utils_launcher.cpp b/src/mongo/shell/shell_utils_launcher.cpp
index 625efa83e1c..58f65570860 100644
--- a/src/mongo/shell/shell_utils_launcher.cpp
+++ b/src/mongo/shell/shell_utils_launcher.cpp
@@ -40,6 +40,8 @@
#include "mongo/client/dbclientinterface.h"
#include "mongo/scripting/engine.h"
#include "mongo/shell/shell_utils.h"
+#include "mongo/util/scopeguard.h"
+#include "mongo/util/signal_win32.h"
namespace mongo {
@@ -66,15 +68,15 @@ namespace mongo {
return _ports.count( port ) == 1;
}
- pid_t ProgramRegistry::pidForPort( int port ) const {
+ ProcessId ProgramRegistry::pidForPort( int port ) const {
boost::recursive_mutex::scoped_lock lk( _mutex );
verify( isPortRegistered( port ) );
return _ports.find( port )->second.first;
}
- int ProgramRegistry::portForPid(pid_t pid) const {
+ int ProgramRegistry::portForPid(ProcessId pid) const {
boost::recursive_mutex::scoped_lock lk(_mutex);
- for (map<int, pair<pid_t, int> >::const_iterator it = _ports.begin();
+ for (map<int, pair<ProcessId, int> >::const_iterator it = _ports.begin();
it != _ports.end(); ++it)
{
if (it->second.first == pid) return it->first;
@@ -83,7 +85,7 @@ namespace mongo {
return -1;
}
- void ProgramRegistry::registerPort( int port, pid_t pid, int output ) {
+ void ProgramRegistry::registerPort( int port, ProcessId pid, int output ) {
boost::recursive_mutex::scoped_lock lk( _mutex );
verify( !isPortRegistered( port ) );
_ports.insert( make_pair( port, make_pair( pid, output ) ) );
@@ -100,24 +102,24 @@ namespace mongo {
void ProgramRegistry::getRegisteredPorts( vector<int> &ports ) {
boost::recursive_mutex::scoped_lock lk( _mutex );
- for( map<int,pair<pid_t,int> >::const_iterator i = _ports.begin(); i != _ports.end();
+ for( map<int,pair<ProcessId,int> >::const_iterator i = _ports.begin(); i != _ports.end();
++i ) {
ports.push_back( i->first );
}
}
- bool ProgramRegistry::isPidRegistered( pid_t pid ) const {
+ bool ProgramRegistry::isPidRegistered( ProcessId pid ) const {
boost::recursive_mutex::scoped_lock lk( _mutex );
return _pids.count( pid ) == 1;
}
- void ProgramRegistry::registerPid( pid_t pid, int output ) {
+ void ProgramRegistry::registerPid( ProcessId pid, int output ) {
boost::recursive_mutex::scoped_lock lk( _mutex );
verify( !isPidRegistered( pid ) );
_pids.insert( make_pair( pid, output ) );
}
- void ProgramRegistry::deletePid(pid_t pid) {
+ void ProgramRegistry::deletePid(ProcessId pid) {
boost::recursive_mutex::scoped_lock lk(_mutex);
if (!isPidRegistered(pid)) {
int port = portForPid(pid);
@@ -129,9 +131,9 @@ namespace mongo {
_pids.erase(pid);
}
- void ProgramRegistry::getRegisteredPids( vector<pid_t> &pids ) {
+ void ProgramRegistry::getRegisteredPids( vector<ProcessId> &pids ) {
boost::recursive_mutex::scoped_lock lk( _mutex );
- for( map<pid_t,int>::const_iterator i = _pids.begin(); i != _pids.end(); ++i ) {
+ for( map<ProcessId,int>::const_iterator i = _pids.begin(); i != _pids.end(); ++i ) {
pids.push_back( i->first );
}
}
@@ -143,7 +145,7 @@ namespace mongo {
mongo::dbexitCalled = true;
}
- void ProgramOutputMultiplexer::appendLine( int port, int pid, const char *line ) {
+ void ProgramOutputMultiplexer::appendLine( int port, ProcessId pid, const char *line ) {
mongo::mutex::scoped_lock lk( mongoProgramOutputMutex );
if( mongo::dbexitCalled ) throw "program is terminating";
stringstream buf;
@@ -152,6 +154,7 @@ namespace mongo {
else
buf << "sh" << pid << "| " << line;
printf( "%s\n", buf.str().c_str() ); // cout << buf.str() << endl;
+ fflush(stdout); // not implicit if stdout isn't directly outputting to a console.
_buffer << buf.str() << endl;
}
@@ -316,10 +319,17 @@ namespace mongo {
boost::filesystem::path ProgramRunner::findProgram( const string &prog ) {
boost::filesystem::path p = prog;
+
#ifdef _WIN32
- p = change_extension(p, ".exe");
+ // The system programs either come versioned in the form of <utility>-<major.minor>
+ // (e.g., mongorestore-2.4) or just <utility>. For windows, the appropriate extension
+ // needs to be appended.
+ //
+ if (p.extension() != ".exe") {
+ p = prog + ".exe";
+ }
#endif
-
+
if( boost::filesystem::exists(p) ) {
#ifndef _WIN32
p = boost::filesystem::initial_path() / p;
@@ -331,10 +341,12 @@ namespace mongo {
boost::filesystem::path t = boost::filesystem::current_path() / p;
if( boost::filesystem::exists(t) ) return t;
}
+
{
boost::filesystem::path t = boost::filesystem::initial_path() / p;
if( boost::filesystem::exists(t) ) return t;
}
+
return p; // not found; might find via system path
}
@@ -399,7 +411,7 @@ namespace mongo {
CloseHandle(pi.hThread);
- _pid = pi.dwProcessId;
+ _pid = ProcessId::fromNative(pi.dwProcessId);
registry._handles.insert( make_pair( _pid, pi.hProcess ) );
#else
@@ -417,14 +429,13 @@ namespace mongo {
env[1] = NULL;
bool isMongos = ( _argv[0].find( "mongos" ) != string::npos );
-
- _pid = fork();
+
+ pid_t nativePid = fork();
+ _pid = ProcessId::fromNative(nativePid);
// Async signal unsafe functions should not be called in the child process.
- if ( _pid == -1 ) {
- verify( _pid != -1 );
- }
- else if ( _pid == 0 ) {
+ verify( nativePid != -1 );
+ if ( nativePid == 0 ) {
// DON'T ASSERT IN THIS BLOCK - very bad things will happen
if ( dup2( child_stdout, STDOUT_FILENO ) == -1 ||
@@ -460,7 +471,7 @@ namespace mongo {
}
//returns true if process exited
- bool wait_for_pid(pid_t pid, bool block=true, int* exit_code=NULL) {
+ 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];
@@ -484,7 +495,7 @@ namespace mongo {
}
#else
int tmp;
- bool ret = (pid == waitpid(pid, &tmp, (block ? 0 : WNOHANG)));
+ bool ret = (pid.toNative() == waitpid(pid.toNative(), &tmp, (block ? 0 : WNOHANG)));
if (exit_code)
*exit_code = WEXITSTATUS(tmp);
return ret;
@@ -502,14 +513,14 @@ namespace mongo {
}
BSONObj CheckProgram(const BSONObj& args, void* data) {
- int pid = singleArg(args).numberInt();
+ ProcessId pid = ProcessId::fromNative(singleArg(args).numberInt());
bool isDead = wait_for_pid(pid, false);
if (isDead) registry.deletePid(pid);
return BSON( string( "" ) << (!isDead) );
}
BSONObj WaitProgram( const BSONObj& a, void* data ) {
- int pid = singleArg( a ).numberInt();
+ ProcessId pid = ProcessId::fromNative(singleArg( a ).numberInt());
BSONObj x = BSON( "" << wait_for_pid( pid ) );
registry.deletePid( pid );
return x;
@@ -520,7 +531,7 @@ namespace mongo {
ProgramRunner r( a );
r.start();
boost::thread t( r );
- return BSON( string( "" ) << int( r.pid() ) );
+ return BSON( string( "" ) << r.pid().asLongLong() );
}
BSONObj RunMongoProgram( const BSONObj &a, void* data ) {
@@ -600,42 +611,72 @@ namespace mongo {
return undefinedReturn;
}
- inline void kill_wrapper( pid_t pid, int sig, int port, const BSONObj& opt ) {
+ 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;
}
- else {
- DBClientConnection conn;
- try {
- conn.connect("127.0.0.1:" + BSONObjBuilder::numStr(port));
- BSONElement authObj = opt["auth"];
+ std::string eventName = getShutdownSignalName(pid.asUInt32());
- 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 );
+ 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();
}
- catch (...) {
- //Do nothing. This command never returns data to the client and the driver doesn't like that.
+ 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, sig );
+ int x = kill( pid.toNative(), sig );
if ( x ) {
if ( errno == ESRCH ) {
}
@@ -648,8 +689,8 @@ namespace mongo {
#endif
}
- int killDb( int port, pid_t _pid, int signal, const BSONObj& opt ) {
- pid_t pid;
+ int killDb( int port, ProcessId _pid, int signal, const BSONObj& opt ) {
+ ProcessId pid;
int exitCode = 0;
if ( port > 0 ) {
if( !registry.isPortRegistered( port ) ) {
@@ -667,10 +708,7 @@ namespace mongo {
int i = 0;
for( ; i < 130; ++i ) {
if ( i == 60 ) {
- char now[64];
- time_t_to_String(time(0), now);
- now[ 20 ] = 0;
- log() << now << " process on port " << port << ", with pid " << pid << " not terminated, sending sigkill" << endl;
+ log() << "process on port " << port << ", with pid " << pid << " not terminated, sending sigkill" << endl;
kill_wrapper( pid, SIGKILL, port, opt );
}
if(wait_for_pid(pid, false, &exitCode))
@@ -678,10 +716,7 @@ namespace mongo {
sleepmillis( 1000 );
}
if ( i == 130 ) {
- char now[64];
- time_t_to_String(time(0), now);
- now[ 20 ] = 0;
- log() << now << " failed to terminate process on port " << port << ", with pid " << pid << endl;
+ log() << "failed to terminate process on port " << port << ", with pid " << pid << endl;
verify( "Failed to terminate process" == 0 );
}
@@ -700,7 +735,7 @@ namespace mongo {
return exitCode;
}
- int killDb( int port, pid_t _pid, int signal ) {
+ int killDb( int port, ProcessId _pid, int signal ) {
BSONObj dummyOpt;
return killDb( port, _pid, signal, dummyOpt );
}
@@ -738,7 +773,7 @@ namespace mongo {
verify( nFields >= 1 && nFields <= 3 );
uassert( 15853 , "stopMongo needs a number" , a.firstElement().isNumber() );
int port = int( a.firstElement().number() );
- int code = killDb( port, 0, getSignal( a ), getStopMongodOpts( a ));
+ int code = killDb( port, ProcessId::fromNative(0), getSignal( a ), getStopMongodOpts( a ));
log() << "shell: stopped mongo program on port " << port << endl;
return BSON( "" << (double)code );
}
@@ -746,7 +781,7 @@ namespace mongo {
BSONObj StopMongoProgramByPid( const BSONObj &a, void* data ) {
verify( a.nFields() == 1 || a.nFields() == 2 );
uassert( 15852 , "stopMongoByPid needs a number" , a.firstElement().isNumber() );
- int pid = int( a.firstElement().number() );
+ ProcessId pid = ProcessId::fromNative(int( a.firstElement().number() ));
int code = killDb( 0, pid, getSignal( a ) );
log() << "shell: stopped mongo program on pid " << pid << endl;
return BSON( "" << (double)code );
@@ -756,10 +791,10 @@ namespace mongo {
vector< int > ports;
registry.getRegisteredPorts( ports );
for( vector< int >::iterator i = ports.begin(); i != ports.end(); ++i )
- killDb( *i, 0, SIGTERM );
- vector< pid_t > pids;
+ killDb( *i, ProcessId::fromNative(0), SIGTERM );
+ vector< ProcessId > pids;
registry.getRegisteredPids( pids );
- for( vector< pid_t >::iterator i = pids.begin(); i != pids.end(); ++i )
+ for( vector< ProcessId >::iterator i = pids.begin(); i != pids.end(); ++i )
killDb( 0, *i, SIGTERM );
}