]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_main.cc
import ceph 14.2.5
[ceph.git] / ceph / src / rgw / rgw_main.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
7c673cae
FG
4#include "common/ceph_argparse.h"
5#include "global/global_init.h"
6#include "global/signal_handler.h"
7#include "common/config.h"
8#include "common/errno.h"
9#include "common/Timer.h"
10#include "common/safe_io.h"
11fdf7f2 11#include "common/TracepointProvider.h"
7c673cae
FG
12#include "include/compat.h"
13#include "include/str_list.h"
224ce89b 14#include "include/stringify.h"
7c673cae
FG
15#include "rgw_common.h"
16#include "rgw_rados.h"
11fdf7f2 17#include "rgw_otp.h"
7c673cae
FG
18#include "rgw_period_pusher.h"
19#include "rgw_realm_reloader.h"
20#include "rgw_rest.h"
21#include "rgw_rest_s3.h"
22#include "rgw_rest_swift.h"
23#include "rgw_rest_admin.h"
24#include "rgw_rest_usage.h"
25#include "rgw_rest_user.h"
26#include "rgw_rest_bucket.h"
27#include "rgw_rest_metadata.h"
28#include "rgw_rest_log.h"
7c673cae
FG
29#include "rgw_rest_config.h"
30#include "rgw_rest_realm.h"
11fdf7f2 31#include "rgw_rest_sts.h"
7c673cae
FG
32#include "rgw_swift_auth.h"
33#include "rgw_log.h"
34#include "rgw_tools.h"
35#include "rgw_resolve.h"
7c673cae
FG
36#include "rgw_request.h"
37#include "rgw_process.h"
38#include "rgw_frontend.h"
94b18763 39#include "rgw_http_client_curl.h"
11fdf7f2 40#include "rgw_perf_counters.h"
eafe8130
TL
41#ifdef WITH_RADOSGW_AMQP_ENDPOINT
42#include "rgw_amqp.h"
43#endif
7c673cae
FG
44#if defined(WITH_RADOSGW_BEAST_FRONTEND)
45#include "rgw_asio_frontend.h"
46#endif /* WITH_RADOSGW_BEAST_FRONTEND */
47
11fdf7f2 48#include "rgw_dmclock_scheduler_ctx.h"
7c673cae 49
11fdf7f2 50#include "services/svc_zone.h"
7c673cae
FG
51
52#ifdef HAVE_SYS_PRCTL_H
53#include <sys/prctl.h>
54#endif
55
56#define dout_subsys ceph_subsys_rgw
57
11fdf7f2
TL
58namespace {
59TracepointProvider::Traits rgw_op_tracepoint_traits("librgw_op_tp.so",
60 "rgw_op_tracing");
61TracepointProvider::Traits rgw_rados_tracepoint_traits("librgw_rados_tp.so",
62 "rgw_rados_tracing");
63}
7c673cae
FG
64
65static sig_t sighandler_alrm;
66
67class RGWProcess;
68
69static int signal_fd[2] = {0, 0};
7c673cae
FG
70
71void signal_shutdown()
72{
11fdf7f2
TL
73 int val = 0;
74 int ret = write(signal_fd[0], (char *)&val, sizeof(val));
75 if (ret < 0) {
76 derr << "ERROR: " << __func__ << ": write() returned "
77 << cpp_strerror(errno) << dendl;
7c673cae
FG
78 }
79}
80
81static void wait_shutdown()
82{
83 int val;
84 int r = safe_read_exact(signal_fd[1], &val, sizeof(val));
85 if (r < 0) {
86 derr << "safe_read_exact returned with error" << dendl;
87 }
88}
89
90static int signal_fd_init()
91{
92 return socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fd);
93}
94
95static void signal_fd_finalize()
96{
97 close(signal_fd[0]);
98 close(signal_fd[1]);
99}
100
101static void handle_sigterm(int signum)
102{
103 dout(1) << __func__ << dendl;
104#if defined(WITH_RADOSGW_FCGI_FRONTEND)
105 FCGX_ShutdownPending();
106#endif
107
108 // send a signal to make fcgi's accept(2) wake up. unfortunately the
109 // initial signal often isn't sufficient because we race with accept's
110 // check of the flag wet by ShutdownPending() above.
111 if (signum != SIGUSR1) {
112 signal_shutdown();
113
114 // safety net in case we get stuck doing an orderly shutdown.
115 uint64_t secs = g_ceph_context->_conf->rgw_exit_timeout_secs;
116 if (secs)
117 alarm(secs);
118 dout(1) << __func__ << " set alarm for " << secs << dendl;
119 }
120
121}
122
123static void godown_alarm(int signum)
124{
125 _exit(0);
126}
127
7c673cae
FG
128
129class C_InitTimeout : public Context {
130public:
131 C_InitTimeout() {}
132 void finish(int r) override {
133 derr << "Initialization timeout, failed to initialize" << dendl;
134 exit(1);
135 }
136};
137
138static int usage()
139{
11fdf7f2
TL
140 cout << "usage: radosgw [options...]" << std::endl;
141 cout << "options:\n";
142 cout << " --rgw-region=<region> region in which radosgw runs\n";
143 cout << " --rgw-zone=<zone> zone in which radosgw runs\n";
144 cout << " --rgw-socket-path=<path> specify a unix domain socket path\n";
145 cout << " -m monaddress[:port] connect to specified monitor\n";
146 cout << " --keyring=<path> path to radosgw keyring\n";
147 cout << " --logfile=<logfile> file to log debug output\n";
148 cout << " --debug-rgw=<log-level>/<memory-level> set radosgw debug level\n";
7c673cae
FG
149 generic_server_usage();
150
151 return 0;
152}
153
154static RGWRESTMgr *set_logging(RGWRESTMgr *mgr)
155{
156 mgr->set_logging(true);
157 return mgr;
158}
159
31f18b77
FG
160static RGWRESTMgr *rest_filter(RGWRados *store, int dialect, RGWRESTMgr *orig)
161{
162 RGWSyncModuleInstanceRef sync_module = store->get_sync_module();
94b18763
FG
163 if (sync_module) {
164 return sync_module->get_rest_filter(dialect, orig);
165 } else {
166 return orig;
167 }
31f18b77
FG
168}
169
7c673cae
FG
170/*
171 * start up the RADOS connection and then handle HTTP messages as they come in
172 */
7c673cae 173int main(int argc, const char **argv)
7c673cae
FG
174{
175 // dout() messages will be sent to stderr, but FCGX wants messages on stdout
176 // Redirect stderr to stdout.
177 TEMP_FAILURE_RETRY(close(STDERR_FILENO));
178 if (TEMP_FAILURE_RETRY(dup2(STDOUT_FILENO, STDERR_FILENO)) < 0) {
179 int err = errno;
180 cout << "failed to redirect stderr to stdout: " << cpp_strerror(err)
181 << std::endl;
182 return ENOSYS;
183 }
184
185 /* alternative default for module */
11fdf7f2
TL
186 map<string,string> defaults = {
187 { "debug_rgw", "1/5" },
188 { "keyring", "$rgw_data/keyring" },
189 { "objecter_inflight_ops", "24576" }
190 };
7c673cae
FG
191
192 vector<const char*> args;
193 argv_to_vec(argc, argv, args);
11fdf7f2
TL
194 if (args.empty()) {
195 cerr << argv[0] << ": -h or --help for usage" << std::endl;
196 exit(1);
197 }
198 if (ceph_argparse_need_usage(args)) {
199 usage();
200 exit(0);
201 }
7c673cae
FG
202
203 // First, let's determine which frontends are configured.
204 int flags = CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS;
11fdf7f2
TL
205 global_pre_init(
206 &defaults, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
207 flags);
7c673cae
FG
208
209 list<string> frontends;
11fdf7f2
TL
210 g_conf().early_expand_meta(g_conf()->rgw_frontends, &cerr);
211 get_str_list(g_conf()->rgw_frontends, ",", frontends);
7c673cae
FG
212 multimap<string, RGWFrontendConfig *> fe_map;
213 list<RGWFrontendConfig *> configs;
214 if (frontends.empty()) {
31f18b77 215 frontends.push_back("civetweb");
7c673cae
FG
216 }
217 for (list<string>::iterator iter = frontends.begin(); iter != frontends.end(); ++iter) {
218 string& f = *iter;
219
91327a77
AA
220 if (f.find("civetweb") != string::npos || f.find("beast") != string::npos) {
221 // If civetweb or beast is configured as a frontend, prevent global_init() from
7c673cae
FG
222 // dropping permissions by setting the appropriate flag.
223 flags |= CINIT_FLAG_DEFER_DROP_PRIVILEGES;
224 if (f.find("port") != string::npos) {
225 // check for the most common ws problems
226 if ((f.find("port=") == string::npos) ||
227 (f.find("port= ") != string::npos)) {
91327a77
AA
228 derr << "WARNING: radosgw frontend config found unexpected spacing around 'port' "
229 << "(ensure frontend port parameter has the form 'port=80' with no spaces "
7c673cae
FG
230 << "before or after '=')" << dendl;
231 }
232 }
233 }
234
235 RGWFrontendConfig *config = new RGWFrontendConfig(f);
236 int r = config->init();
237 if (r < 0) {
238 delete config;
239 cerr << "ERROR: failed to init config: " << f << std::endl;
240 return EINVAL;
241 }
242
243 configs.push_back(config);
244
245 string framework = config->get_framework();
246 fe_map.insert(pair<string, RGWFrontendConfig*>(framework, config));
247 }
248
249 // Now that we've determined which frontend(s) to use, continue with global
250 // initialization. Passing false as the final argument ensures that
251 // global_pre_init() is not invoked twice.
252 // claim the reference and release it after subsequent destructors have fired
11fdf7f2 253 auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT,
7c673cae
FG
254 CODE_ENVIRONMENT_DAEMON,
255 flags, "rgw_data", false);
256
7c673cae 257 // maintain existing region root pool for new multisite objects
11fdf7f2
TL
258 if (!g_conf()->rgw_region_root_pool.empty()) {
259 const char *root_pool = g_conf()->rgw_region_root_pool.c_str();
260 if (g_conf()->rgw_zonegroup_root_pool.empty()) {
261 g_conf().set_val_or_die("rgw_zonegroup_root_pool", root_pool);
7c673cae 262 }
11fdf7f2
TL
263 if (g_conf()->rgw_period_root_pool.empty()) {
264 g_conf().set_val_or_die("rgw_period_root_pool", root_pool);
7c673cae 265 }
11fdf7f2
TL
266 if (g_conf()->rgw_realm_root_pool.empty()) {
267 g_conf().set_val_or_die("rgw_realm_root_pool", root_pool);
7c673cae
FG
268 }
269 }
270
271 // for region -> zonegroup conversion (must happen before common_init_finish())
11fdf7f2
TL
272 if (!g_conf()->rgw_region.empty() && g_conf()->rgw_zonegroup.empty()) {
273 g_conf().set_val_or_die("rgw_zonegroup", g_conf()->rgw_region.c_str());
7c673cae
FG
274 }
275
11fdf7f2 276 if (g_conf()->daemonize) {
7c673cae
FG
277 global_init_daemonize(g_ceph_context);
278 }
279 Mutex mutex("main");
280 SafeTimer init_timer(g_ceph_context, mutex);
281 init_timer.init();
282 mutex.Lock();
11fdf7f2 283 init_timer.add_event_after(g_conf()->rgw_init_timeout, new C_InitTimeout);
7c673cae
FG
284 mutex.Unlock();
285
7c673cae
FG
286 common_init_finish(g_ceph_context);
287
11fdf7f2
TL
288 init_async_signal_handler();
289 register_async_signal_handler(SIGHUP, sighup_handler);
290
291 TracepointProvider::initialize<rgw_rados_tracepoint_traits>(g_ceph_context);
292 TracepointProvider::initialize<rgw_op_tracepoint_traits>(g_ceph_context);
293
7c673cae
FG
294 int r = rgw_tools_init(g_ceph_context);
295 if (r < 0) {
296 derr << "ERROR: unable to initialize rgw tools" << dendl;
297 return -r;
298 }
299
300 rgw_init_resolver();
94b18763 301 rgw::curl::setup_curl(fe_map);
11fdf7f2
TL
302 rgw_http_client_init(g_ceph_context);
303
7c673cae
FG
304#if defined(WITH_RADOSGW_FCGI_FRONTEND)
305 FCGX_Init();
306#endif
307
11fdf7f2
TL
308 RGWRados *store =
309 RGWStoreManager::get_storage(g_ceph_context,
310 g_conf()->rgw_enable_gc_threads,
311 g_conf()->rgw_enable_lc_threads,
312 g_conf()->rgw_enable_quota_threads,
313 g_conf()->rgw_run_sync_thread,
314 g_conf().get_val<bool>("rgw_dynamic_resharding"),
315 g_conf()->rgw_cache_enabled);
7c673cae
FG
316 if (!store) {
317 mutex.Lock();
318 init_timer.cancel_all_events();
319 init_timer.shutdown();
320 mutex.Unlock();
321
322 derr << "Couldn't init storage provider (RADOS)" << dendl;
323 return EIO;
324 }
325 r = rgw_perf_start(g_ceph_context);
326 if (r < 0) {
327 derr << "ERROR: failed starting rgw perf" << dendl;
328 return -r;
329 }
330
11fdf7f2 331 rgw_rest_init(g_ceph_context, store, store->svc.zone->get_zonegroup());
7c673cae
FG
332
333 mutex.Lock();
334 init_timer.cancel_all_events();
335 init_timer.shutdown();
336 mutex.Unlock();
337
338 rgw_user_init(store);
339 rgw_bucket_init(store->meta_mgr);
11fdf7f2 340 rgw_otp_init(store);
7c673cae
FG
341 rgw_log_usage_init(g_ceph_context, store);
342
343 RGWREST rest;
344
345 list<string> apis;
346
11fdf7f2 347 get_str_list(g_conf()->rgw_enable_apis, apis);
7c673cae
FG
348
349 map<string, bool> apis_map;
350 for (list<string>::iterator li = apis.begin(); li != apis.end(); ++li) {
351 apis_map[*li] = true;
352 }
353
11fdf7f2
TL
354 /* warn about insecure keystone secret config options */
355 if (!(g_ceph_context->_conf->rgw_keystone_admin_token.empty() ||
356 g_ceph_context->_conf->rgw_keystone_admin_password.empty())) {
357 dout(0) << "WARNING: rgw_keystone_admin_token and rgw_keystone_admin_password should be avoided as they can expose secrets. Prefer the new rgw_keystone_admin_token_path and rgw_keystone_admin_password_path options, which read their secrets from files." << dendl;
358 }
359
7c673cae
FG
360 // S3 website mode is a specialization of S3
361 const bool s3website_enabled = apis_map.count("s3website") > 0;
11fdf7f2 362 const bool sts_enabled = apis_map.count("sts") > 0;
eafe8130 363 const bool pubsub_enabled = apis_map.count("pubsub") > 0;
7c673cae 364 // Swift API entrypoint could placed in the root instead of S3
11fdf7f2 365 const bool swift_at_root = g_conf()->rgw_swift_url_prefix == "/";
7c673cae
FG
366 if (apis_map.count("s3") > 0 || s3website_enabled) {
367 if (! swift_at_root) {
31f18b77 368 rest.register_default_mgr(set_logging(rest_filter(store, RGW_REST_S3,
eafe8130 369 new RGWRESTMgr_S3(s3website_enabled, sts_enabled, pubsub_enabled))));
7c673cae
FG
370 } else {
371 derr << "Cannot have the S3 or S3 Website enabled together with "
372 << "Swift API placed in the root of hierarchy" << dendl;
373 return EINVAL;
374 }
375 }
376
eafe8130
TL
377 if (pubsub_enabled) {
378#ifdef WITH_RADOSGW_AMQP_ENDPOINT
379 if (!rgw::amqp::init(cct.get())) {
380 dout(1) << "ERROR: failed to initialize AMQP manager" << dendl;
381 }
382#endif
383 }
384
7c673cae
FG
385 if (apis_map.count("swift") > 0) {
386 RGWRESTMgr_SWIFT* const swift_resource = new RGWRESTMgr_SWIFT;
387
11fdf7f2 388 if (! g_conf()->rgw_cross_domain_policy.empty()) {
7c673cae
FG
389 swift_resource->register_resource("crossdomain.xml",
390 set_logging(new RGWRESTMgr_SWIFT_CrossDomain));
391 }
392
393 swift_resource->register_resource("healthcheck",
394 set_logging(new RGWRESTMgr_SWIFT_HealthCheck));
395
396 swift_resource->register_resource("info",
397 set_logging(new RGWRESTMgr_SWIFT_Info));
398
399 if (! swift_at_root) {
11fdf7f2 400 rest.register_resource(g_conf()->rgw_swift_url_prefix,
31f18b77
FG
401 set_logging(rest_filter(store, RGW_REST_SWIFT,
402 swift_resource)));
7c673cae 403 } else {
11fdf7f2 404 if (store->svc.zone->get_zonegroup().zones.size() > 1) {
7c673cae
FG
405 derr << "Placing Swift API in the root of URL hierarchy while running"
406 << " multi-site configuration requires another instance of RadosGW"
407 << " with S3 API enabled!" << dendl;
408 }
409
410 rest.register_default_mgr(set_logging(swift_resource));
411 }
412 }
413
414 if (apis_map.count("swift_auth") > 0) {
11fdf7f2 415 rest.register_resource(g_conf()->rgw_swift_auth_entry,
7c673cae
FG
416 set_logging(new RGWRESTMgr_SWIFT_Auth));
417 }
418
419 if (apis_map.count("admin") > 0) {
420 RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
421 admin_resource->register_resource("usage", new RGWRESTMgr_Usage);
422 admin_resource->register_resource("user", new RGWRESTMgr_User);
423 admin_resource->register_resource("bucket", new RGWRESTMgr_Bucket);
424
425 /*Registering resource for /admin/metadata */
426 admin_resource->register_resource("metadata", new RGWRESTMgr_Metadata);
427 admin_resource->register_resource("log", new RGWRESTMgr_Log);
7c673cae
FG
428 admin_resource->register_resource("config", new RGWRESTMgr_Config);
429 admin_resource->register_resource("realm", new RGWRESTMgr_Realm);
11fdf7f2 430 rest.register_resource(g_conf()->rgw_admin_entry, admin_resource);
7c673cae
FG
431 }
432
433 /* Initialize the registry of auth strategies which will coordinate
434 * the dynamic reconfiguration. */
435 auto auth_registry = \
11fdf7f2 436 rgw::auth::StrategyRegistry::create(g_ceph_context, store);
7c673cae
FG
437
438 /* Header custom behavior */
11fdf7f2
TL
439 rest.register_x_headers(g_conf()->rgw_log_http_headers);
440
441 if (cct->_conf.get_val<std::string>("rgw_scheduler_type") == "dmclock" &&
442 !cct->check_experimental_feature_enabled("dmclock")){
443 derr << "dmclock scheduler type is experimental and needs to be"
444 << "set in the option enable experimental data corrupting features"
445 << dendl;
446 return EINVAL;
447 }
448
449 rgw::dmclock::SchedulerCtx sched_ctx{cct.get()};
7c673cae
FG
450
451 OpsLogSocket *olog = NULL;
452
11fdf7f2
TL
453 if (!g_conf()->rgw_ops_log_socket_path.empty()) {
454 olog = new OpsLogSocket(g_ceph_context, g_conf()->rgw_ops_log_data_backlog);
455 olog->init(g_conf()->rgw_ops_log_socket_path);
7c673cae
FG
456 }
457
458 r = signal_fd_init();
459 if (r < 0) {
460 derr << "ERROR: unable to initialize signal fds" << dendl;
461 exit(1);
462 }
463
7c673cae
FG
464 register_async_signal_handler(SIGTERM, handle_sigterm);
465 register_async_signal_handler(SIGINT, handle_sigterm);
466 register_async_signal_handler(SIGUSR1, handle_sigterm);
467 sighandler_alrm = signal(SIGALRM, godown_alarm);
468
224ce89b
WB
469 map<string, string> service_map_meta;
470 service_map_meta["pid"] = stringify(getpid());
471
7c673cae
FG
472 list<RGWFrontend *> fes;
473
224ce89b
WB
474 int fe_count = 0;
475
7c673cae 476 for (multimap<string, RGWFrontendConfig *>::iterator fiter = fe_map.begin();
224ce89b 477 fiter != fe_map.end(); ++fiter, ++fe_count) {
7c673cae
FG
478 RGWFrontendConfig *config = fiter->second;
479 string framework = config->get_framework();
480 RGWFrontend *fe = NULL;
481
482 if (framework == "civetweb" || framework == "mongoose") {
224ce89b 483 framework = "civetweb";
7c673cae
FG
484 std::string uri_prefix;
485 config->get_val("prefix", "", &uri_prefix);
486
487 RGWProcessEnv env = { store, &rest, olog, 0, uri_prefix, auth_registry };
11fdf7f2 488 //TODO: move all of scheduler initializations to frontends?
7c673cae 489
11fdf7f2 490 fe = new RGWCivetWebFrontend(env, config, sched_ctx);
7c673cae
FG
491 }
492 else if (framework == "loadgen") {
493 int port;
494 config->get_val("port", 80, &port);
495 std::string uri_prefix;
496 config->get_val("prefix", "", &uri_prefix);
497
498 RGWProcessEnv env = { store, &rest, olog, port, uri_prefix, auth_registry };
499
500 fe = new RGWLoadGenFrontend(env, config);
501 }
502#if defined(WITH_RADOSGW_BEAST_FRONTEND)
11fdf7f2 503 else if (framework == "beast") {
7c673cae
FG
504 int port;
505 config->get_val("port", 80, &port);
506 std::string uri_prefix;
507 config->get_val("prefix", "", &uri_prefix);
508 RGWProcessEnv env{ store, &rest, olog, port, uri_prefix, auth_registry };
11fdf7f2 509 fe = new RGWAsioFrontend(env, config, sched_ctx);
7c673cae
FG
510 }
511#endif /* WITH_RADOSGW_BEAST_FRONTEND */
512#if defined(WITH_RADOSGW_FCGI_FRONTEND)
513 else if (framework == "fastcgi" || framework == "fcgi") {
224ce89b 514 framework = "fastcgi";
7c673cae
FG
515 std::string uri_prefix;
516 config->get_val("prefix", "", &uri_prefix);
517 RGWProcessEnv fcgi_pe = { store, &rest, olog, 0, uri_prefix, auth_registry };
518
519 fe = new RGWFCGXFrontend(fcgi_pe, config);
520 }
521#endif /* WITH_RADOSGW_FCGI_FRONTEND */
522
224ce89b
WB
523 service_map_meta["frontend_type#" + stringify(fe_count)] = framework;
524 service_map_meta["frontend_config#" + stringify(fe_count)] = config->get_config();
525
7c673cae
FG
526 if (fe == NULL) {
527 dout(0) << "WARNING: skipping unknown framework: " << framework << dendl;
528 continue;
529 }
530
531 dout(0) << "starting handler: " << fiter->first << dendl;
532 int r = fe->init();
533 if (r < 0) {
534 derr << "ERROR: failed initializing frontend" << dendl;
535 return -r;
536 }
537 r = fe->run();
538 if (r < 0) {
539 derr << "ERROR: failed run" << dendl;
540 return -r;
541 }
542
543 fes.push_back(fe);
544 }
545
224ce89b
WB
546 r = store->register_to_service_map("rgw", service_map_meta);
547 if (r < 0) {
548 derr << "ERROR: failed to register to service map: " << cpp_strerror(-r) << dendl;
549
550 /* ignore error */
551 }
552
553
7c673cae
FG
554 // add a watcher to respond to realm configuration changes
555 RGWPeriodPusher pusher(store);
11fdf7f2 556 RGWFrontendPauser pauser(fes, &pusher);
224ce89b 557 RGWRealmReloader reloader(store, service_map_meta, &pauser);
7c673cae 558
11fdf7f2 559 RGWRealmWatcher realm_watcher(g_ceph_context, store->svc.zone->get_realm());
7c673cae
FG
560 realm_watcher.add_watcher(RGWRealmNotify::Reload, reloader);
561 realm_watcher.add_watcher(RGWRealmNotify::ZonesNeedPeriod, pusher);
562
563#if defined(HAVE_SYS_PRCTL_H)
564 if (prctl(PR_SET_DUMPABLE, 1) == -1) {
565 cerr << "warning: unable to set dumpable flag: " << cpp_strerror(errno) << std::endl;
566 }
567#endif
568
569 wait_shutdown();
570
571 derr << "shutting down" << dendl;
572
573 for (list<RGWFrontend *>::iterator liter = fes.begin(); liter != fes.end();
574 ++liter) {
575 RGWFrontend *fe = *liter;
576 fe->stop();
577 }
578
579 for (list<RGWFrontend *>::iterator liter = fes.begin(); liter != fes.end();
580 ++liter) {
581 RGWFrontend *fe = *liter;
582 fe->join();
583 delete fe;
584 }
585
586 for (list<RGWFrontendConfig *>::iterator liter = configs.begin();
587 liter != configs.end(); ++liter) {
588 RGWFrontendConfig *fec = *liter;
589 delete fec;
590 }
591
b32b8144 592 unregister_async_signal_handler(SIGHUP, sighup_handler);
7c673cae
FG
593 unregister_async_signal_handler(SIGTERM, handle_sigterm);
594 unregister_async_signal_handler(SIGINT, handle_sigterm);
595 unregister_async_signal_handler(SIGUSR1, handle_sigterm);
596 shutdown_async_signal_handler();
597
598 rgw_log_usage_finalize();
599
600 delete olog;
601
602 RGWStoreManager::close_storage(store);
11fdf7f2 603 rgw::auth::s3::LDAPEngine::shutdown();
7c673cae
FG
604 rgw_tools_cleanup();
605 rgw_shutdown_resolver();
11fdf7f2 606 rgw_http_client_cleanup();
94b18763 607 rgw::curl::cleanup_curl();
eafe8130
TL
608#ifdef WITH_RADOSGW_AMQP_ENDPOINT
609 rgw::amqp::shutdown();
610#endif
7c673cae
FG
611
612 rgw_perf_stop(g_ceph_context);
613
614 dout(1) << "final shutdown" << dendl;
615
616 signal_fd_finalize();
617
618 return 0;
619}