get_str_list(str, sup_list);
for (list<string>::iterator iter = sup_list.begin(); iter != sup_list.end(); ++iter) {
if (iter->compare("cephx") == 0) {
- dout(10) << "supporting cephx auth protocol" << dendl;
auth_supported[CEPH_AUTH_CEPHX] = true;
} else if (iter->compare("none") == 0) {
auth_supported[CEPH_AUTH_NONE] = true;
- dout(10) << "supporting *none* auth protocol" << dendl;
} else {
- dout(0) << "WARNING: unknown auth protocol defined: " << *iter << dendl;
+ derr << "WARNING: unknown auth protocol defined: " << *iter << dendl;
}
}
_supported_initialized = true;
* Driver for a particular algorithm
*
* To use these functions, you need to call ceph::crypto::init(), see
- * common/ceph_crypto.h. common_init already does this for you.
+ * common/ceph_crypto.h. common_init_finish does this for you.
*/
class CryptoHandler {
public:
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(&g_conf, 0);
EntityName ename(g_conf.name);
const char *me = argv[0];
argv_to_vec(argc, argv, args);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
std::string val;
for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS);
- keyring_init(&g_conf);
vector<const char*> nargs;
FOR_EACH_ARG(args) {
exit(1);
}
- common_prefork();
childpid = fork();
}
+ common_init_finish(&g_conf, 0);
+
if (childpid == 0) {
//cout << "child, mounting" << std::endl;
::close(fd[0]);
cout << "cfuse[" << getpid() << "]: starting ceph client" << std::endl;
-
- // if we forked, re-init things
- if (g_conf.daemonize)
- common_postfork();
messenger->start_with_nonce(getpid());
// start client
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_MDS, CODE_ENVIRONMENT_DAEMON, 0);
- keyring_init(&g_conf);
// mds specific args
int shadow = 0;
messenger->set_policy(entity_name_t::TYPE_CLIENT,
SimpleMessenger::Policy::stateful_server(supported, 0));
- if (shadow == MDSMap::STATE_ONESHOT_REPLAY ? false : g_conf.daemonize)
- common_init_daemonize(&g_conf);
+ if (shadow == MDSMap::STATE_ONESHOT_REPLAY)
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
messenger->start();
// start mds
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_MON, CODE_ENVIRONMENT_DAEMON, 0);
- keyring_init(&g_conf);
FOR_EACH_ARG(args) {
if (CEPH_ARGPARSE_EQ("mkfs", '\0')) {
// -- mkfs --
if (mkfs) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
if (g_conf.monmap.empty() || !osdmapfn)
usage();
// bind
SimpleMessenger *messenger = new SimpleMessenger();
-
int rank = monmap.get_rank(g_conf.name.get_id());
cout << "starting " << g_conf.name << " rank " << rank
messenger->set_default_send_priority(CEPH_MSG_PRIO_HIGH);
Monitor *mon = new Monitor(g_conf.name.get_id(), &store, messenger, &monmap);
- if (g_conf.daemonize)
- common_init_daemonize(&g_conf);
+ common_init_finish(&g_conf, 0);
messenger->start();
uint64_t supported =
}
template <typename charT, typename traits>
-void DoutStreambuf<charT, traits>::handle_stderr_closed()
+void DoutStreambuf<charT, traits>::handle_stderr_shutdown()
{
- // should hold the dout_lock here
+ DoutLocker _dout_locker;
flags &= ~DOUTSB_FLAG_STDERR;
}
int DoutStreambuf<charT, traits>::
handle_pid_change(const md_config_t *conf)
{
- // should hold the dout_lock here
+ DoutLocker _dout_locker;
if (!(flags & DOUTSB_FLAG_OFILE))
return 0;
// Call when you close stderr. Not strictly necessary, since we would get an
// error the next time we tried to write to stdedrr. But nicer than waiting
// for the error to happen.
- void handle_stderr_closed();
+ void handle_stderr_shutdown();
virtual const char** get_tracked_conf_keys() const;
#elif USE_NSS
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
void ceph::crypto::init() {
- pthread_mutex_lock(&lock);
- if (crypto_init) {
- pthread_mutex_unlock(&lock);
- return;
- }
crypto_init = true;
- pthread_mutex_unlock(&lock);
-
SECStatus s;
s = NSS_NoDB_Init(NULL);
assert(s == SECSuccess);
}
void ceph::crypto::shutdown() {
- pthread_mutex_lock(&lock);
- assert(crypto_init);
crypto_init = false;
- pthread_mutex_unlock(&lock);
SECStatus s;
s = NSS_Shutdown();
assert(s == SECSuccess);
conf->set_val_or_die("daemonize", "false");
break;
}
-
- ceph::crypto::init();
return conf;
}
}
}
-// TODO: until this is exposed to libceph/librados somehow, the
-// library users cannot fork and expect to keep using the library
-void common_prefork() {
- // NSS is evil and breaks in forked children; shut it down properly
- // and re-init in both parent and child, after the fork
- ceph::crypto::shutdown();
-}
-
-void common_postfork() {
- ceph::crypto::init();
-}
-
static void pidfile_remove_void(void)
{
pidfile_remove();
}
-// callers that fork must either use common_init_daemonize for that, or
-// call common_prefork/common_postfork around the bit where they fork
-void common_init_daemonize(const md_config_t *conf)
+/* Map stderr to /dev/null. This isn't really re-entrant; we rely on the old unix
+ * behavior that the file descriptor that gets assigned is the lowest
+ * available one.
+ */
+int common_init_shutdown_stderr(const md_config_t *conf)
{
- common_prefork();
+ TEMP_FAILURE_RETRY(close(STDERR_FILENO));
+ if (open("/dev/null", O_RDONLY) < 0) {
+ int err = errno;
+ derr << "common_init_shutdown_stderr: open(/dev/null) failed: error "
+ << err << dendl;
+ return 1;
+ }
+ conf->_doss->handle_stderr_shutdown();
+ return 0;
+}
+static void common_init_daemonize(const md_config_t *conf, int flags)
+{
int num_threads = Thread::get_num_threads();
if (num_threads > 1) {
derr << "common_init_daemonize: BUG: there are " << num_threads - 1
exit(1);
}
- int ret = daemon(1, 0);
+ int ret = daemon(1, 1);
if (ret) {
ret = errno;
derr << "common_init_daemonize: BUG: daemon error: "
<< "to run at exit." << dendl;
}
- // move these things into observers.
+ /* This is the old trick where we make file descriptors 0, 1, and possibly 2
+ * point to /dev/null.
+ *
+ * We have to do this because otherwise some arbitrary call to open() later
+ * in the program might get back one of these file descriptors. It's hard to
+ * guarantee that nobody ever writes to stdout, even though they're not
+ * supposed to.
+ */
+ TEMP_FAILURE_RETRY(close(STDIN_FILENO));
+ if (open("/dev/null", O_RDONLY) < 0) {
+ int err = errno;
+ derr << "common_init_daemonize: open(/dev/null) failed: error "
+ << err << dendl;
+ exit(1);
+ }
+ TEMP_FAILURE_RETRY(close(STDOUT_FILENO));
+ if (open("/dev/null", O_RDONLY) < 0) {
+ int err = errno;
+ derr << "common_init_daemonize: open(/dev/null) failed: error "
+ << err << dendl;
+ exit(1);
+ }
+ if (!(flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)) {
+ ret = common_init_shutdown_stderr(conf);
+ if (ret) {
+ derr << "common_init_daemonize: common_init_shutdown_stderr failed with "
+ << "error code " << ret << dendl;
+ exit(1);
+ }
+ }
pidfile_write(&g_conf);
- dout_handle_daemonize(&g_conf);
-
+ ret = conf->_doss->handle_pid_change(&g_conf);
+ if (ret) {
+ derr << "common_init_daemonize: _doss->handle_pid_change failed with "
+ << "error code " << ret << dendl;
+ exit(1);
+ }
dout(1) << "finished common_init_daemonize" << dendl;
+}
- common_postfork();
+void common_init_finish(const md_config_t *conf, int flags)
+{
+ if ((g_code_env == CODE_ENVIRONMENT_DAEMON) && (g_conf.daemonize)) {
+ common_init_daemonize(conf, flags);
+ }
+ ceph::crypto::init();
+ keyring_init(&g_conf);
}
+
// By default, don't read a configuration file
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE = 0x2,
+
+ // Don't close stderr
+ CINIT_FLAG_NO_CLOSE_STDERR = 0x4,
};
int keyring_init(md_config_t *conf);
void common_init(std::vector < const char* >& args,
uint32_t module_type, code_environment_t code_env, int flags);
void output_ceph_version();
-void common_prefork();
-void common_postfork();
-void common_init_daemonize(const md_config_t *conf);
+int common_init_shutdown_stderr(const md_config_t *conf);
+void common_init_finish(const md_config_t *conf, int flags);
#endif
*/
pthread_mutex_t _dout_lock = PTHREAD_MUTEX_INITIALIZER;
-int dout_handle_daemonize(md_config_t *conf)
-{
- DoutLocker _dout_locker;
-
- conf->_doss->handle_stderr_closed();
- return conf->_doss->handle_pid_change(&g_conf);
-}
-
void output_ceph_version()
{
char buf[1024];
class md_config_t;
extern pthread_mutex_t _dout_lock;
-extern int dout_handle_daemonize(md_config_t *conf);
-
extern void dout_emergency(const char * const str);
extern void dout_emergency(const std::string &str);
}
}
- if (!mkfs)
- keyring_init(&g_conf);
-
if (dump_pg_log) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
bufferlist bl;
int r = bl.read_file(dump_pg_log);
if (r >= 0) {
usage();
}
- // get monmap
- RotatingKeyRing rkeys(CEPH_ENTITY_TYPE_OSD, &g_keyring);
- MonClient mc(&rkeys);
- if (mc.build_initial_monmap() < 0)
- return -1;
-
if (mkfs) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
+ RotatingKeyRing rkeys(CEPH_ENTITY_TYPE_OSD, &g_keyring);
+ MonClient mc(&rkeys);
+ if (mc.build_initial_monmap() < 0)
+ return -1;
if (mc.get_monmap_privately() < 0)
return -1;
*_dout << " for osd" << whoami << " fsid " << mc.monmap.fsid << dendl;
}
if (mkkey) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
EntityName ename(g_conf.name);
EntityAuth eauth;
eauth.key.create(CEPH_CRYPTO_AES);
if (mkfs || mkkey)
exit(0);
if (mkjournal) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
int err = OSD::mkjournal(g_conf.osd_data, g_conf.osd_journal);
if (err < 0) {
derr << TEXT_RED << " ** ERROR: error creating fresh journal " << g_conf.osd_journal
exit(0);
}
if (flushjournal) {
+ g_conf.daemonize = false;
+ common_init_finish(&g_conf, 0);
int err = OSD::flushjournal(g_conf.osd_data, g_conf.osd_journal);
if (err < 0) {
derr << TEXT_RED << " ** ERROR: error flushing journal " << g_conf.osd_journal
cluster_messenger->set_policy(entity_name_t::TYPE_CLIENT,
SimpleMessenger::Policy::stateless_server(0, 0));
-
+ // Set up crypto, daemonize, etc.
+ // Leave stderr open in case we need to report errors.
+ common_init_finish(&g_conf, CINIT_FLAG_NO_CLOSE_STDERR);
+ RotatingKeyRing rkeys(CEPH_ENTITY_TYPE_OSD, &g_keyring);
+ MonClient mc(&rkeys);
+ if (mc.build_initial_monmap() < 0)
+ return -1;
OSD *osd = new OSD(whoami, cluster_messenger, client_messenger, messenger_hb, &mc,
g_conf.osd_data, g_conf.osd_journal);
-
int err = osd->pre_init();
if (err < 0) {
derr << TEXT_RED << " ** ERROR: initializing osd failed: " << cpp_strerror(-err)
return 1;
}
- if (g_conf.daemonize)
- common_init_daemonize(&g_conf);
+ // Now close the standard file descriptors
+ common_init_shutdown_stderr(&g_conf);
+
client_messenger->start();
messenger_hb->start();
cluster_messenger->start();
argv_to_vec(argc, argv, args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
parse_syn_options(args); // for SyntheticClient
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
vec_to_argv(args, argc, argv);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
// args
if (args.size() != 4)
}
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
FOR_EACH_ARG(args) {
usage_exit();
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(&g_conf, 0);
FOR_EACH_ARG(args) {
if (CEPH_ARGPARSE_EQ("print", '\0')) {
CEPH_ARGPARSE_SET_ARG_VAL(&print, OPT_BOOL);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(&g_conf, 0);
const char *me = argv[0];
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
std::map < std::string, std::string > opts;
std::vector<const char*>::iterator i;
int opt_cmd = OPT_NO_CMD;
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
const char *poolname = NULL;
uint64_t size = 0;
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
const char *user_id = 0;
const char *access_key = 0;
argv_to_vec(argc, argv, args);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
if (!RGWAccess::init_storage_provider("rados", &g_conf)) {
derr << "Couldn't init storage provider (RADOS)" << dendl;
sighandler_usr1 = signal(SIGUSR1, godown_handler);
sighandler_alrm = signal(SIGALRM, godown_alarm);
- common_postfork();
while (FCGX_Accept(&fcgx.in, &fcgx.out, &fcgx.err, &fcgx.envp) >= 0)
{
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
// args
if (args.size() < 3) return -1;
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
DoutStreambuf<char> *dos = new DoutStreambuf<char>();
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
DEFINE_CONF_VARS(usage);
FOR_EACH_ARG(args) {
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
int ret;
Mutex safe_timer_lock("safe_timer_lock");
argv_to_vec(argc, argv, args);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
string val;
string oid("test_object");
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
// args
if (args.size() < 2) return -1;
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(&g_conf, 0);
vec_to_argv(args, argc, argv);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
vec_to_argv(args, argc, argv);
env_to_vec(args);
common_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- keyring_init(&g_conf);
+ common_init_finish(&g_conf, 0);
vec_to_argv(args, argc, argv);