| /*****************************************************************************\ |
| * slurmdbd.c - functions for SlurmDBD |
| ***************************************************************************** |
| * Copyright (C) 2002-2007 The Regents of the University of California. |
| * Copyright (C) 2008 Lawrence Livermore National Security. |
| * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). |
| * Written by Morris Jette <jette@llnl.gov> |
| * CODE-OCEC-09-009. All rights reserved. |
| * |
| * This file is part of SLURM, a resource management program. |
| * For details, see <http://www.schedmd.com/slurmdocs/>. |
| * Please also read the included file: DISCLAIMER. |
| * |
| * SLURM is free software; you can redistribute it and/or modify it under |
| * the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * In addition, as a special exception, the copyright holders give permission |
| * to link the code of portions of this program with the OpenSSL library under |
| * certain conditions as described in each individual source file, and |
| * distribute linked combinations including the two. You must obey the GNU |
| * General Public License in all respects for all of the code used other than |
| * OpenSSL. If you modify file(s) with this exception, you may extend this |
| * exception to your version of the file(s), but you are not obligated to do |
| * so. If you do not wish to do so, delete this exception statement from your |
| * version. If you delete this exception statement from all source files in |
| * the program, then also delete it here. |
| * |
| * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| * details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with SLURM; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| \*****************************************************************************/ |
| |
| #ifdef HAVE_CONFIG_H |
| # include "config.h" |
| #endif |
| #if HAVE_SYS_PRCTL_H |
| # include <sys/prctl.h> |
| #endif |
| #include <grp.h> |
| #include <pthread.h> |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/resource.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #include "src/common/daemonize.h" |
| #include "src/common/fd.h" |
| #include "src/common/log.h" |
| #include "src/common/read_config.h" |
| #include "src/common/slurm_accounting_storage.h" |
| #include "src/common/slurm_auth.h" |
| #include "src/common/uid.h" |
| #include "src/common/xmalloc.h" |
| #include "src/common/xsignal.h" |
| #include "src/common/xstring.h" |
| #include "src/common/proc_args.h" |
| |
| #include "src/slurmdbd/read_config.h" |
| #include "src/slurmdbd/rpc_mgr.h" |
| #include "src/slurmdbd/backup.h" |
| |
| /* Global variables */ |
| time_t shutdown_time = 0; /* when shutdown request arrived */ |
| |
| /* Local variables */ |
| static int dbd_sigarray[] = { /* blocked signals for this process */ |
| SIGINT, SIGTERM, SIGCHLD, SIGUSR1, |
| SIGUSR2, SIGTSTP, SIGXCPU, SIGQUIT, |
| SIGPIPE, SIGALRM, SIGABRT, SIGHUP, 0 }; |
| static int debug_level = 0; /* incremented for -v on command line */ |
| static int foreground = 0; /* run process as a daemon */ |
| static log_options_t log_opts = /* Log to stderr & syslog */ |
| LOG_OPTS_INITIALIZER; |
| static int new_nice = 0; |
| static pthread_t rpc_handler_thread; /* thread ID for RPC hander */ |
| static pthread_t signal_handler_thread; /* thread ID for signal hander */ |
| static pthread_t rollup_handler_thread; /* thread ID for rollup hander */ |
| static pthread_mutex_t rollup_lock = PTHREAD_MUTEX_INITIALIZER; |
| static bool running_rollup = 0; |
| |
| /* Local functions */ |
| static void _become_slurm_user(void); |
| static void _daemonize(void); |
| static void _default_sigaction(int sig); |
| static void _init_config(void); |
| static void _init_pidfile(void); |
| static void _kill_old_slurmdbd(void); |
| static void _parse_commandline(int argc, char *argv[]); |
| static void _request_registrations(void *db_conn); |
| static void _rollup_handler_cancel(); |
| static void *_rollup_handler(void *no_data); |
| static int _send_slurmctld_register_req(slurmdb_cluster_rec_t *cluster_rec); |
| static void _set_work_dir(void); |
| static void *_signal_handler(void *no_data); |
| static void _update_logging(bool startup); |
| static void _update_nice(void); |
| static void _usage(char *prog_name); |
| |
| /* main - slurmctld main function, start various threads and process RPCs */ |
| int main(int argc, char *argv[]) |
| { |
| pthread_attr_t thread_attr; |
| char node_name[128]; |
| void *db_conn = NULL; |
| assoc_init_args_t assoc_init_arg; |
| |
| _init_config(); |
| log_init(argv[0], log_opts, LOG_DAEMON, NULL); |
| if (read_slurmdbd_conf()) |
| exit(1); |
| _parse_commandline(argc, argv); |
| _update_logging(true); |
| _update_nice(); |
| |
| if (slurm_auth_init(NULL) != SLURM_SUCCESS) { |
| fatal("Unable to initialize %s authentication plugin", |
| slurmdbd_conf->auth_type); |
| } |
| if (slurm_acct_storage_init(NULL) != SLURM_SUCCESS) { |
| fatal("Unable to initialize %s accounting storage plugin", |
| slurmdbd_conf->storage_type); |
| } |
| _kill_old_slurmdbd(); |
| if (foreground == 0) |
| _daemonize(); |
| |
| /* |
| * Need to create pidfile here in case we setuid() below |
| * (init_pidfile() exits if it can't initialize pid file). |
| * On Linux we also need to make this setuid job explicitly |
| * able to write a core dump. |
| * This also has to happen after daemon(), which closes all fd's, |
| * so we keep the write lock of the pidfile. |
| */ |
| _init_pidfile(); |
| _become_slurm_user(); |
| if (foreground == 0) |
| _set_work_dir(); |
| log_config(); |
| |
| #ifdef PR_SET_DUMPABLE |
| if (prctl(PR_SET_DUMPABLE, 1) < 0) |
| debug ("Unable to set dumpable to 1"); |
| #endif /* PR_SET_DUMPABLE */ |
| |
| if (xsignal_block(dbd_sigarray) < 0) |
| error("Unable to block signals"); |
| |
| /* Create attached thread for signal handling */ |
| slurm_attr_init(&thread_attr); |
| if (pthread_create(&signal_handler_thread, &thread_attr, |
| _signal_handler, NULL)) |
| fatal("pthread_create %m"); |
| slurm_attr_destroy(&thread_attr); |
| |
| memset(&assoc_init_arg, 0, sizeof(assoc_init_args_t)); |
| |
| /* If we are tacking wckey we need to cache |
| wckeys, if we aren't only cache the users and qos */ |
| assoc_init_arg.cache_level = ASSOC_MGR_CACHE_USER | ASSOC_MGR_CACHE_QOS; |
| if (slurmdbd_conf->track_wckey) |
| assoc_init_arg.cache_level |= ASSOC_MGR_CACHE_WCKEY; |
| |
| db_conn = acct_storage_g_get_connection(NULL, 0, false, NULL); |
| if (assoc_mgr_init(db_conn, &assoc_init_arg, errno) == SLURM_ERROR) { |
| error("Problem getting cache of data"); |
| acct_storage_g_close_connection(&db_conn); |
| goto end_it; |
| } |
| |
| if (gethostname_short(node_name, sizeof(node_name))) |
| fatal("getnodename: %m"); |
| |
| while (1) { |
| if (slurmdbd_conf->dbd_backup && |
| (!strcmp(node_name, slurmdbd_conf->dbd_backup) || |
| !strcmp(slurmdbd_conf->dbd_backup, "localhost"))) { |
| info("slurmdbd running in background mode"); |
| have_control = false; |
| backup = true; |
| run_backup(); |
| if (!shutdown_time) |
| assoc_mgr_refresh_lists(db_conn, NULL); |
| } else if (slurmdbd_conf->dbd_host && |
| (!strcmp(slurmdbd_conf->dbd_host, node_name) || |
| !strcmp(slurmdbd_conf->dbd_host, "localhost"))) { |
| backup = false; |
| have_control = true; |
| } else { |
| fatal("This host not configured to run SlurmDBD " |
| "(%s != %s | (backup) %s)", |
| node_name, slurmdbd_conf->dbd_host, |
| slurmdbd_conf->dbd_backup); |
| } |
| |
| if (!shutdown_time) { |
| /* Create attached thread to process incoming RPCs */ |
| slurm_attr_init(&thread_attr); |
| if (pthread_create(&rpc_handler_thread, &thread_attr, |
| rpc_mgr, NULL)) |
| fatal("pthread_create error %m"); |
| slurm_attr_destroy(&thread_attr); |
| } |
| |
| if (!shutdown_time) { |
| /* Create attached thread to do usage rollup */ |
| slurm_attr_init(&thread_attr); |
| if (pthread_create(&rollup_handler_thread, |
| &thread_attr, |
| _rollup_handler, db_conn)) |
| fatal("pthread_create error %m"); |
| slurm_attr_destroy(&thread_attr); |
| } |
| |
| /* Daemon is fully operational here */ |
| if (!shutdown_time || primary_resumed) { |
| shutdown_time = 0; |
| info("slurmdbd version %s started", |
| SLURM_VERSION_STRING); |
| if (backup) |
| run_backup(); |
| } |
| |
| _request_registrations(db_conn); |
| |
| /* this is only ran if not backup */ |
| if (rollup_handler_thread) |
| pthread_join(rollup_handler_thread, NULL); |
| if (rpc_handler_thread) |
| pthread_join(rpc_handler_thread, NULL); |
| |
| if (backup && primary_resumed) { |
| shutdown_time = 0; |
| info("Backup has given up control"); |
| } |
| |
| if (shutdown_time) |
| break; |
| } |
| /* Daemon termination handled here */ |
| |
| if (signal_handler_thread) |
| pthread_join(signal_handler_thread, NULL); |
| |
| end_it: |
| acct_storage_g_close_connection(&db_conn); |
| |
| if (slurmdbd_conf->pid_file && |
| (unlink(slurmdbd_conf->pid_file) < 0)) { |
| verbose("Unable to remove pidfile '%s': %m", |
| slurmdbd_conf->pid_file); |
| } |
| |
| assoc_mgr_fini(NULL); |
| slurm_acct_storage_fini(); |
| slurm_auth_fini(); |
| log_fini(); |
| free_slurmdbd_conf(); |
| exit(0); |
| } |
| |
| extern void shutdown_threads() |
| { |
| shutdown_time = time(NULL); |
| rpc_mgr_wake(); |
| _rollup_handler_cancel(); |
| } |
| |
| /* Reset some of the processes resource limits to the hard limits */ |
| static void _init_config(void) |
| { |
| struct rlimit rlim; |
| |
| if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { |
| rlim.rlim_cur = rlim.rlim_max; |
| (void) setrlimit(RLIMIT_NOFILE, &rlim); |
| } |
| if (getrlimit(RLIMIT_CORE, &rlim) == 0) { |
| rlim.rlim_cur = rlim.rlim_max; |
| (void) setrlimit(RLIMIT_CORE, &rlim); |
| } |
| if (getrlimit(RLIMIT_STACK, &rlim) == 0) { |
| /* slurmctld can spawn lots of pthreads. |
| * Set the (per thread) stack size to a |
| * more "reasonable" value to avoid running |
| * out of virtual memory and dying */ |
| rlim.rlim_cur = rlim.rlim_max; |
| (void) setrlimit(RLIMIT_STACK, &rlim); |
| } |
| if (getrlimit(RLIMIT_DATA, &rlim) == 0) { |
| rlim.rlim_cur = rlim.rlim_max; |
| (void) setrlimit(RLIMIT_DATA, &rlim); |
| } |
| } |
| |
| /* |
| * _parse_commandline - parse and process any command line arguments |
| * IN argc - number of command line arguments |
| * IN argv - the command line arguments |
| * IN/OUT conf_ptr - pointer to current configuration, update as needed |
| */ |
| static void _parse_commandline(int argc, char *argv[]) |
| { |
| int c = 0; |
| char *tmp_char; |
| |
| opterr = 0; |
| while ((c = getopt(argc, argv, "Dhn:vV")) != -1) |
| switch (c) { |
| case 'D': |
| foreground = 1; |
| break; |
| case 'h': |
| _usage(argv[0]); |
| exit(0); |
| break; |
| case 'n': |
| new_nice = strtol(optarg, &tmp_char, 10); |
| if (tmp_char[0] != '\0') { |
| error("Invalid option for -n option (nice " |
| "value), ignored"); |
| new_nice = 0; |
| } |
| break; |
| case 'v': |
| debug_level++; |
| break; |
| case 'V': |
| print_slurm_version(); |
| exit(0); |
| break; |
| default: |
| _usage(argv[0]); |
| exit(1); |
| } |
| } |
| |
| /* _usage - print a message describing the command line arguments of |
| * slurmctld */ |
| static void _usage(char *prog_name) |
| { |
| fprintf(stderr, "Usage: %s [OPTIONS]\n", prog_name); |
| fprintf(stderr, " -D \t" |
| "Run daemon in foreground.\n"); |
| fprintf(stderr, " -h \t" |
| "Print this help message.\n"); |
| fprintf(stderr, " -n value \t" |
| "Run the daemon at the specified nice value.\n"); |
| fprintf(stderr, " -v \t" |
| "Verbose mode. Multiple -v's increase verbosity.\n"); |
| fprintf(stderr, " -V \t" |
| "Print version information and exit.\n"); |
| } |
| |
| /* Reset slurmctld logging based upon configuration parameters */ |
| static void _update_logging(bool startup) |
| { |
| /* Preserve execute line arguments (if any) */ |
| if (debug_level) { |
| slurmdbd_conf->debug_level = MIN( |
| (LOG_LEVEL_INFO + debug_level), |
| (LOG_LEVEL_END - 1)); |
| } |
| |
| log_opts.stderr_level = slurmdbd_conf->debug_level; |
| log_opts.logfile_level = slurmdbd_conf->debug_level; |
| log_opts.syslog_level = slurmdbd_conf->debug_level; |
| |
| if (foreground) |
| log_opts.syslog_level = LOG_LEVEL_QUIET; |
| else { |
| log_opts.stderr_level = LOG_LEVEL_QUIET; |
| if (slurmdbd_conf->log_file) |
| log_opts.syslog_level = LOG_LEVEL_QUIET; |
| } |
| |
| log_alter(log_opts, SYSLOG_FACILITY_DAEMON, slurmdbd_conf->log_file); |
| if (startup && slurmdbd_conf->log_file) { |
| int rc; |
| gid_t slurm_user_gid; |
| slurm_user_gid = gid_from_uid(slurmdbd_conf->slurm_user_id); |
| rc = chown(slurmdbd_conf->log_file, |
| slurmdbd_conf->slurm_user_id, slurm_user_gid); |
| if (rc) { |
| error("chown(%s, %d, %d): %m", |
| slurmdbd_conf->log_file, |
| (int) slurmdbd_conf->slurm_user_id, |
| (int) slurm_user_gid); |
| } |
| } |
| } |
| |
| /* Reset slurmd nice value */ |
| static void _update_nice(void) |
| { |
| int cur_nice; |
| id_t pid; |
| |
| if (new_nice == 0) /* No change */ |
| return; |
| |
| pid = getpid(); |
| cur_nice = getpriority(PRIO_PROCESS, pid); |
| if (cur_nice == new_nice) |
| return; |
| if (setpriority(PRIO_PROCESS, pid, new_nice)) |
| error("Unable to reset nice value to %d: %m", new_nice); |
| } |
| |
| /* Kill the currently running slurmdbd */ |
| static void _kill_old_slurmdbd(void) |
| { |
| int fd; |
| pid_t oldpid; |
| |
| if (slurmdbd_conf->pid_file == NULL) { |
| error("No PidFile configured"); |
| return; |
| } |
| |
| oldpid = read_pidfile(slurmdbd_conf->pid_file, &fd); |
| if (oldpid != (pid_t) 0) { |
| info("Killing old slurmdbd[%ld]", (long) oldpid); |
| kill(oldpid, SIGTERM); |
| |
| /* |
| * Wait for previous daemon to terminate |
| */ |
| if (fd_get_readw_lock(fd) < 0) |
| fatal("Unable to wait for readw lock: %m"); |
| (void) close(fd); /* Ignore errors */ |
| } |
| } |
| |
| /* Create the PidFile if one is configured */ |
| static void _init_pidfile(void) |
| { |
| if (slurmdbd_conf->pid_file == NULL) { |
| error("No PidFile configured"); |
| return; |
| } |
| |
| /* Don't close the fd returned here since we need to keep the |
| fd open to maintain the write lock. |
| */ |
| create_pidfile(slurmdbd_conf->pid_file, slurmdbd_conf->slurm_user_id); |
| } |
| |
| /* Become a daemon (child of init) and |
| * "cd" to the LogFile directory (if one is configured) */ |
| static void _daemonize(void) |
| { |
| if (daemon(1, 1)) |
| error("daemon(): %m"); |
| log_alter(log_opts, LOG_DAEMON, slurmdbd_conf->log_file); |
| } |
| |
| static void _set_work_dir(void) |
| { |
| bool success = false; |
| |
| if (slurmdbd_conf->log_file && |
| (slurmdbd_conf->log_file[0] == '/')) { |
| char *slash_ptr, *work_dir; |
| work_dir = xstrdup(slurmdbd_conf->log_file); |
| slash_ptr = strrchr(work_dir, '/'); |
| if (slash_ptr == work_dir) |
| work_dir[1] = '\0'; |
| else |
| slash_ptr[0] = '\0'; |
| if ((access(work_dir, W_OK) != 0) || (chdir(work_dir) < 0)) |
| error("chdir(%s): %m", work_dir); |
| else |
| success = true; |
| xfree(work_dir); |
| } |
| |
| if (!success) { |
| if ((access("/var/tmp", W_OK) != 0) || |
| (chdir("/var/tmp") < 0)) { |
| error("chdir(/var/tmp): %m"); |
| } else |
| info("chdir to /var/tmp"); |
| } |
| } |
| |
| static void _request_registrations(void *db_conn) |
| { |
| List cluster_list = acct_storage_g_get_clusters( |
| db_conn, getuid(), NULL); |
| ListIterator itr; |
| slurmdb_cluster_rec_t *cluster_rec = NULL; |
| |
| if (!cluster_list) |
| return; |
| itr = list_iterator_create(cluster_list); |
| while ((cluster_rec = list_next(itr))) { |
| if (!cluster_rec->control_port |
| || (cluster_rec->rpc_version < 9)) |
| continue; |
| if (_send_slurmctld_register_req(cluster_rec) != SLURM_SUCCESS) |
| /* mark this cluster as unresponsive */ |
| clusteracct_storage_g_fini_ctld(db_conn, cluster_rec); |
| } |
| list_iterator_destroy(itr); |
| list_destroy(cluster_list); |
| } |
| |
| static void _rollup_handler_cancel() |
| { |
| if (running_rollup) |
| debug("Waiting for rollup thread to finish."); |
| slurm_mutex_lock(&rollup_lock); |
| if (rollup_handler_thread) |
| pthread_cancel(rollup_handler_thread); |
| slurm_mutex_unlock(&rollup_lock); |
| } |
| |
| /* _rollup_handler - Process rollup duties */ |
| static void *_rollup_handler(void *db_conn) |
| { |
| time_t start_time = time(NULL); |
| time_t next_time; |
| /* int sigarray[] = {SIGUSR1, 0}; */ |
| struct tm tm; |
| |
| (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
| (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); |
| |
| if (!localtime_r(&start_time, &tm)) { |
| fatal("Couldn't get localtime for rollup handler %ld", |
| (long)start_time); |
| return NULL; |
| } |
| |
| while (1) { |
| if (!db_conn) |
| break; |
| /* run the roll up */ |
| slurm_mutex_lock(&rollup_lock); |
| running_rollup = 1; |
| debug2("running rollup at %s", ctime(&start_time)); |
| acct_storage_g_roll_usage(db_conn, 0, 0, 1); |
| running_rollup = 0; |
| slurm_mutex_unlock(&rollup_lock); |
| |
| /* sleep for an hour */ |
| tm.tm_sec = 0; |
| tm.tm_min = 0; |
| tm.tm_hour++; |
| tm.tm_isdst = -1; |
| next_time = mktime(&tm); |
| |
| /* get the time now we have rolled usage */ |
| start_time = time(NULL); |
| |
| sleep((next_time-start_time)); |
| |
| start_time = time(NULL); |
| if (!localtime_r(&start_time, &tm)) { |
| fatal("Couldn't get localtime for rollup handler %ld", |
| (long)start_time); |
| return NULL; |
| } |
| /* Just in case some new uids were added to the system |
| pick them up here. */ |
| assoc_mgr_set_missing_uids(); |
| /* repeat ;) */ |
| |
| } |
| |
| return NULL; |
| } |
| |
| /* |
| * send_slurmctld_register_req - request register from slurmctld |
| * IN host: control host of cluster |
| * IN port: control port of cluster |
| * IN rpc_version: rpc version of cluster |
| * RET: error code |
| */ |
| static int _send_slurmctld_register_req(slurmdb_cluster_rec_t *cluster_rec) |
| { |
| slurm_addr_t ctld_address; |
| slurm_fd_t fd; |
| int rc = SLURM_SUCCESS; |
| |
| slurm_set_addr_char(&ctld_address, cluster_rec->control_port, |
| cluster_rec->control_host); |
| fd = slurm_open_msg_conn(&ctld_address); |
| if (fd < 0) { |
| rc = SLURM_ERROR; |
| } else { |
| slurm_msg_t out_msg; |
| slurm_msg_t_init(&out_msg); |
| out_msg.msg_type = ACCOUNTING_REGISTER_CTLD; |
| out_msg.flags = SLURM_GLOBAL_AUTH_KEY; |
| slurm_send_node_msg(fd, &out_msg); |
| /* We probably need to add matching recv_msg function |
| * for an arbitray fd or should these be fire |
| * and forget? For this, that we can probably |
| * forget about it */ |
| slurm_close_stream(fd); |
| } |
| return rc; |
| } |
| |
| /* _signal_handler - Process daemon-wide signals */ |
| static void *_signal_handler(void *no_data) |
| { |
| int rc, sig; |
| int sig_array[] = {SIGINT, SIGTERM, SIGHUP, SIGABRT, 0}; |
| sigset_t set; |
| |
| (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
| (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); |
| |
| /* Make sure no required signals are ignored (possibly inherited) */ |
| _default_sigaction(SIGINT); |
| _default_sigaction(SIGTERM); |
| _default_sigaction(SIGHUP); |
| _default_sigaction(SIGABRT); |
| |
| while (1) { |
| xsignal_sigset_create(sig_array, &set); |
| rc = sigwait(&set, &sig); |
| if (rc == EINTR) |
| continue; |
| switch (sig) { |
| case SIGHUP: /* kill -1 */ |
| info("Reconfigure signal (SIGHUP) received"); |
| read_slurmdbd_conf(); |
| assoc_mgr_set_missing_uids(); |
| _update_logging(false); |
| break; |
| case SIGINT: /* kill -2 or <CTRL-C> */ |
| case SIGTERM: /* kill -15 */ |
| info("Terminate signal (SIGINT or SIGTERM) received"); |
| shutdown_threads(); |
| return NULL; /* Normal termination */ |
| case SIGABRT: /* abort */ |
| info("SIGABRT received"); |
| abort(); /* Should terminate here */ |
| shutdown_threads(); |
| return NULL; |
| default: |
| error("Invalid signal (%d) received", sig); |
| } |
| } |
| |
| } |
| |
| /* Reset some signals to their default state to clear any |
| * inherited signal states */ |
| static void _default_sigaction(int sig) |
| { |
| struct sigaction act; |
| |
| if (sigaction(sig, NULL, &act)) { |
| error("sigaction(%d): %m", sig); |
| return; |
| } |
| if (act.sa_handler != SIG_IGN) |
| return; |
| |
| act.sa_handler = SIG_DFL; |
| if (sigaction(sig, &act, NULL)) |
| error("sigaction(%d): %m", sig); |
| } |
| |
| static void _become_slurm_user(void) |
| { |
| gid_t slurm_user_gid; |
| |
| /* Determine SlurmUser gid */ |
| slurm_user_gid = gid_from_uid(slurmdbd_conf->slurm_user_id); |
| if (slurm_user_gid == (gid_t) -1) { |
| fatal("Failed to determine gid of SlurmUser(%u)", |
| slurmdbd_conf->slurm_user_id); |
| } |
| |
| /* Initialize supplementary groups ID list for SlurmUser */ |
| if (getuid() == 0) { |
| /* root does not need supplementary groups */ |
| if ((slurmdbd_conf->slurm_user_id == 0) && |
| (setgroups(0, NULL) != 0)) { |
| fatal("Failed to drop supplementary groups, " |
| "setgroups: %m"); |
| } else if ((slurmdbd_conf->slurm_user_id != getuid()) && |
| initgroups(slurmdbd_conf->slurm_user_name, |
| slurm_user_gid)) { |
| fatal("Failed to set supplementary groups, " |
| "initgroups: %m"); |
| } |
| } else { |
| info("Not running as root. Can't drop supplementary groups"); |
| } |
| |
| /* Set GID to GID of SlurmUser */ |
| if ((slurm_user_gid != getegid()) && |
| (setgid(slurm_user_gid))) { |
| fatal("Failed to set GID to %d", slurm_user_gid); |
| } |
| |
| /* Set UID to UID of SlurmUser */ |
| if ((slurmdbd_conf->slurm_user_id != getuid()) && |
| (setuid(slurmdbd_conf->slurm_user_id))) { |
| fatal("Can not set uid to SlurmUser(%u): %m", |
| slurmdbd_conf->slurm_user_id); |
| } |
| } |