2
* Copyright (C) 2008 10gen Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU Affero General Public License, version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Affero General Public License for more details.
13
* You should have received a copy of the GNU Affero General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
#include "mongo/pch.h"
19
#include "mongo/db/initialize_server_global_state.h"
21
#include <boost/filesystem/operations.hpp>
24
#include <sys/types.h>
28
#include "mongo/db/auth/authorization_manager.h"
29
#include "mongo/db/auth/security_key.h"
30
#include "mongo/db/cmdline.h"
31
#include "mongo/util/log.h"
32
#include "mongo/util/net/listen.h"
33
#include "mongo/util/processinfo.h"
35
namespace fs = boost::filesystem;
40
// support for exit value propagation with fork
41
void launchSignal( int sig ) {
42
if ( sig == SIGUSR2 ) {
45
if ( cur == cmdLine.parentProc || cur == cmdLine.leaderProc ) {
46
// signal indicates successful start allowing us to exit
52
static void setupLaunchSignals() {
53
verify( signal(SIGUSR2 , launchSignal ) != SIG_ERR );
56
void CmdLine::launchOk() {
57
if ( cmdLine.doFork ) {
58
// killing leader will propagate to parent
59
verify( kill( cmdLine.leaderProc, SIGUSR2 ) == 0 );
64
bool initializeServerGlobalState(bool isMongodShutdownSpecialCase) {
66
Listener::globalTicketHolder.resize( cmdLine.maxConns );
69
if (!fs::is_directory(cmdLine.socket)) {
70
cout << cmdLine.socket << " must be a directory" << endl;
75
fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog);
80
cmdLine.parentProc = getpid();
82
// facilitate clean exit when child starts successfully
85
cout << "about to fork child process, waiting until server is ready for connections."
88
pid_t child1 = fork();
90
cout << "ERROR: stage 1 fork() failed: " << errnoWithDescription();
94
// this is run in the original parent process
96
waitpid(child1, &pstat, 0);
98
if (WIFEXITED(pstat)) {
99
if (WEXITSTATUS(pstat)) {
100
cout << "ERROR: child process failed, exited with error number "
101
<< WEXITSTATUS(pstat) << endl;
104
cout << "child process started successfully, parent exiting" << endl;
107
_exit(WEXITSTATUS(pstat));
113
if ( chdir("/") < 0 ) {
114
cout << "Cant chdir() while forking server process: " << strerror(errno) << endl;
119
cmdLine.leaderProc = getpid();
121
pid_t child2 = fork();
123
cout << "ERROR: stage 2 fork() failed: " << errnoWithDescription();
127
// this is run in the middle process
129
cout << "forked process: " << child2 << endl;
130
waitpid(child2, &pstat, 0);
132
if ( WIFEXITED(pstat) ) {
133
_exit( WEXITSTATUS(pstat) );
139
// this is run in the final child process (the server)
141
// stdout handled in initLogging
143
//freopen("/dev/null", "w", stdout);
148
FILE* f = freopen("/dev/null", "w", stderr);
150
cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl;
154
f = freopen("/dev/null", "r", stdin);
156
cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl;
161
if (cmdLine.logWithSyslog) {
163
sb << cmdLine.binaryName << "." << cmdLine.port;
164
Logstream::useSyslog( sb.str().c_str() );
167
if (!cmdLine.logpath.empty() && !isMongodShutdownSpecialCase) {
168
fassert(16448, !cmdLine.logWithSyslog);
169
string absoluteLogpath = boost::filesystem::absolute(
170
cmdLine.logpath, cmdLine.cwd).string();
171
if (!initLogging(absoluteLogpath, cmdLine.logAppend)) {
172
cout << "Bad logpath value: \"" << absoluteLogpath << "\"; terminating." << endl;
177
if (!cmdLine.pidFile.empty()) {
178
writePidFile(cmdLine.pidFile);
181
if (!cmdLine.keyFile.empty()) {
183
if (!setUpSecurityKey(cmdLine.keyFile)) {
184
// error message printed in setUpPrivateKey
194
static void ignoreSignal( int sig ) {}
196
void setupCoreSignals() {
198
verify( signal(SIGHUP , ignoreSignal ) != SIG_ERR );
199
verify( signal(SIGUSR2, ignoreSignal ) != SIG_ERR );