]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_main.cc
6d26302516db8be37a176116b4d4dc9583d40ec8
[ceph.git] / ceph / src / rgw / rgw_main.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include <boost/intrusive/list.hpp>
5 #include "common/ceph_argparse.h"
6 #include "global/global_init.h"
7 #include "global/signal_handler.h"
8 #include "common/config.h"
9 #include "common/errno.h"
10 #include "common/Timer.h"
11 #include "common/TracepointProvider.h"
12 #include "rgw_main.h"
13 #include "rgw_signal.h"
14 #include "rgw_common.h"
15 #include "rgw_lib.h"
16 #include "rgw_log.h"
17
18 #ifdef HAVE_SYS_PRCTL_H
19 #include <sys/prctl.h>
20 #endif
21
22 using namespace std;
23
24 static constexpr auto dout_subsys = ceph_subsys_rgw;
25
26 static sig_t sighandler_alrm;
27
28 static void godown_alarm(int signum)
29 {
30 _exit(0);
31 }
32
33 class C_InitTimeout : public Context {
34 public:
35 C_InitTimeout() {}
36 void finish(int r) override {
37 derr << "Initialization timeout, failed to initialize" << dendl;
38 exit(1);
39 }
40 };
41
42 static int usage()
43 {
44 cout << "usage: radosgw [options...]" << std::endl;
45 cout << "options:\n";
46 cout << " --rgw-region=<region> region in which radosgw runs\n";
47 cout << " --rgw-zone=<zone> zone in which radosgw runs\n";
48 cout << " --rgw-socket-path=<path> specify a unix domain socket path\n";
49 cout << " -m monaddress[:port] connect to specified monitor\n";
50 cout << " --keyring=<path> path to radosgw keyring\n";
51 cout << " --logfile=<logfile> file to log debug output\n";
52 cout << " --debug-rgw=<log-level>/<memory-level> set radosgw debug level\n";
53 generic_server_usage();
54
55 return 0;
56 }
57
58 /*
59 * start up the RADOS connection and then handle HTTP messages as they come in
60 */
61 int main(int argc, char *argv[])
62 {
63 int r{0};
64
65 // dout() messages will be sent to stderr, but FCGX wants messages on stdout
66 // Redirect stderr to stdout.
67 TEMP_FAILURE_RETRY(close(STDERR_FILENO));
68 if (TEMP_FAILURE_RETRY(dup2(STDOUT_FILENO, STDERR_FILENO)) < 0) {
69 int err = errno;
70 cout << "failed to redirect stderr to stdout: " << cpp_strerror(err)
71 << std::endl;
72 return ENOSYS;
73 }
74
75 /* alternative default for module */
76 map<std::string,std::string> defaults = {
77 { "debug_rgw", "1/5" },
78 { "keyring", "$rgw_data/keyring" },
79 { "objecter_inflight_ops", "24576" },
80 // require a secure mon connection by default
81 { "ms_mon_client_mode", "secure" },
82 { "auth_client_required", "cephx" }
83 };
84
85 auto args = argv_to_vec(argc, argv);
86 if (args.empty()) {
87 cerr << argv[0] << ": -h or --help for usage" << std::endl;
88 exit(1);
89 }
90 if (ceph_argparse_need_usage(args)) {
91 usage();
92 exit(0);
93 }
94
95 int flags = CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS;
96 // Prevent global_init() from dropping permissions until frontends can bind
97 // privileged ports
98 flags |= CINIT_FLAG_DEFER_DROP_PRIVILEGES;
99
100 auto cct = rgw_global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT,
101 CODE_ENVIRONMENT_DAEMON, flags);
102
103 DoutPrefix dp(cct.get(), dout_subsys, "rgw main: ");
104 rgw::AppMain main(&dp);
105
106 main.init_frontends1(false /* nfs */);
107 main.init_numa();
108
109 if (g_conf()->daemonize) {
110 global_init_daemonize(g_ceph_context);
111 }
112 ceph::mutex mutex = ceph::make_mutex("main");
113 SafeTimer init_timer(g_ceph_context, mutex);
114 init_timer.init();
115 mutex.lock();
116 init_timer.add_event_after(g_conf()->rgw_init_timeout, new C_InitTimeout);
117 mutex.unlock();
118
119 common_init_finish(g_ceph_context);
120 init_async_signal_handler();
121
122 /* XXXX check locations thru sighandler_alrm */
123 register_async_signal_handler(SIGHUP, rgw::signal::sighup_handler);
124 r = rgw::signal::signal_fd_init();
125 if (r < 0) {
126 derr << "ERROR: unable to initialize signal fds" << dendl;
127 exit(1);
128 }
129
130 register_async_signal_handler(SIGTERM, rgw::signal::handle_sigterm);
131 register_async_signal_handler(SIGINT, rgw::signal::handle_sigterm);
132 register_async_signal_handler(SIGUSR1, rgw::signal::handle_sigterm);
133 sighandler_alrm = signal(SIGALRM, godown_alarm);
134
135 main.init_perfcounters();
136 main.init_http_clients();
137
138 main.init_storage();
139 if (! main.get_driver()) {
140 mutex.lock();
141 init_timer.cancel_all_events();
142 init_timer.shutdown();
143 mutex.unlock();
144
145 derr << "Couldn't init storage provider (RADOS)" << dendl;
146 return EIO;
147 }
148
149 main.cond_init_apis();
150
151 mutex.lock();
152 init_timer.cancel_all_events();
153 init_timer.shutdown();
154 mutex.unlock();
155
156 main.init_ldap();
157 main.init_opslog();
158 main.init_tracepoints();
159 main.init_lua();
160 main.init_frontends2(nullptr /* RGWLib */);
161 main.init_notification_endpoints();
162
163 #if defined(HAVE_SYS_PRCTL_H)
164 if (prctl(PR_SET_DUMPABLE, 1) == -1) {
165 cerr << "warning: unable to set dumpable flag: " << cpp_strerror(errno) << std::endl;
166 }
167 #endif
168
169 rgw::signal::wait_shutdown();
170
171 derr << "shutting down" << dendl;
172
173 const auto finalize_async_signals = []() {
174 unregister_async_signal_handler(SIGHUP, rgw::signal::sighup_handler);
175 unregister_async_signal_handler(SIGTERM, rgw::signal::handle_sigterm);
176 unregister_async_signal_handler(SIGINT, rgw::signal::handle_sigterm);
177 unregister_async_signal_handler(SIGUSR1, rgw::signal::handle_sigterm);
178 shutdown_async_signal_handler();
179 };
180
181 main.shutdown(finalize_async_signals);
182
183 dout(1) << "final shutdown" << dendl;
184
185 rgw::signal::signal_fd_finalize();
186
187 return 0;
188 } /* main(int argc, char* argv[]) */