Merge pull request #9197 from poettering/make-main-shorter
some smaller changes to make PID1's main() a bit shorter
This commit is contained in:
@@ -228,10 +228,10 @@ finish:
|
||||
}
|
||||
|
||||
static int drop_from_file(const char *fn, uint64_t keep) {
|
||||
int r, k;
|
||||
uint32_t hi, lo;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
uint64_t current, after;
|
||||
char *p;
|
||||
uint32_t hi, lo;
|
||||
int r, k;
|
||||
|
||||
r = read_one_line_file(fn, &p);
|
||||
if (r < 0)
|
||||
@@ -241,8 +241,6 @@ static int drop_from_file(const char *fn, uint64_t keep) {
|
||||
assert_cc(sizeof(lo) == sizeof(unsigned));
|
||||
|
||||
k = sscanf(p, "%u %u", &lo, &hi);
|
||||
free(p);
|
||||
|
||||
if (k != 2)
|
||||
return -EIO;
|
||||
|
||||
@@ -255,13 +253,7 @@ static int drop_from_file(const char *fn, uint64_t keep) {
|
||||
lo = (unsigned) (after & 0xFFFFFFFFULL);
|
||||
hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
|
||||
|
||||
if (asprintf(&p, "%u %u", lo, hi) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE);
|
||||
free(p);
|
||||
|
||||
return r;
|
||||
return write_string_filef(fn, WRITE_STRING_FILE_CREATE, "%u %u", lo, hi);
|
||||
}
|
||||
|
||||
int capability_bounding_set_drop_usermode(uint64_t keep) {
|
||||
|
||||
@@ -930,3 +930,27 @@ int fd_reopen(int fd, int flags) {
|
||||
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
int read_nr_open(void) {
|
||||
_cleanup_free_ char *nr_open = NULL;
|
||||
int r;
|
||||
|
||||
/* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the
|
||||
* hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */
|
||||
|
||||
r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
|
||||
else {
|
||||
int v;
|
||||
|
||||
r = safe_atoi(nr_open, &v);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
|
||||
else
|
||||
return v;
|
||||
}
|
||||
|
||||
/* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
|
||||
return 1024 * 1024;
|
||||
}
|
||||
|
||||
@@ -108,3 +108,5 @@ static inline int make_null_stdio(void) {
|
||||
})
|
||||
|
||||
int fd_reopen(int fd, int flags);
|
||||
|
||||
int read_nr_open(void);
|
||||
|
||||
@@ -206,6 +206,25 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_string_filef(
|
||||
const char *fn,
|
||||
WriteStringFileFlags flags,
|
||||
const char *format, ...) {
|
||||
|
||||
_cleanup_free_ char *p = NULL;
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, format);
|
||||
r = vasprintf(&p, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return write_string_file(fn, p, flags);
|
||||
}
|
||||
|
||||
int read_one_line_file(const char *fn, char **line) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
@@ -39,6 +39,8 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
|
||||
return write_string_file_ts(fn, line, flags, NULL);
|
||||
}
|
||||
|
||||
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
|
||||
|
||||
int read_one_line_file(const char *fn, char **line);
|
||||
int read_full_file(const char *fn, char **contents, size_t *size);
|
||||
int read_full_stream(FILE *f, char **contents, size_t *size);
|
||||
|
||||
+79
-94
@@ -311,6 +311,7 @@ static int parse_confirm_spawn(const char *value, char **console) {
|
||||
s = strjoin("/dev/", value);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
*console = s;
|
||||
return 0;
|
||||
}
|
||||
@@ -731,6 +732,10 @@ static void set_manager_defaults(Manager *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Propagates the various default unit property settings into the manager object, i.e. properties that do not
|
||||
* affect the manager itself, but are just what newly allocated units will have set if they haven't set
|
||||
* anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */
|
||||
|
||||
m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
|
||||
m->default_std_output = arg_default_std_output;
|
||||
m->default_std_error = arg_default_std_error;
|
||||
@@ -755,6 +760,9 @@ static void set_manager_settings(Manager *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
|
||||
* itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
|
||||
|
||||
m->confirm_spawn = arg_confirm_spawn;
|
||||
m->service_watchdogs = arg_service_watchdogs;
|
||||
m->runtime_watchdog = arg_runtime_watchdog;
|
||||
@@ -1136,10 +1144,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
|
||||
}
|
||||
|
||||
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
|
||||
struct rlimit nl;
|
||||
int r;
|
||||
int min_max;
|
||||
_cleanup_free_ char *nr_open = NULL;
|
||||
int r, nr;
|
||||
|
||||
assert(saved_rlimit);
|
||||
|
||||
@@ -1160,17 +1165,9 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
|
||||
arg_default_rlimit[RLIMIT_NOFILE] = rl;
|
||||
}
|
||||
|
||||
/* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
|
||||
r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
|
||||
if (r >= 0)
|
||||
r = safe_atoi(nr_open, &min_max);
|
||||
/* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
|
||||
if (r < 0)
|
||||
min_max = 1024 * 1024;
|
||||
|
||||
/* Bump up the resource limit for ourselves substantially */
|
||||
nl.rlim_cur = nl.rlim_max = min_max;
|
||||
r = setrlimit_closest(RLIMIT_NOFILE, &nl);
|
||||
/* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
|
||||
nr = read_nr_open();
|
||||
r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
|
||||
|
||||
@@ -1270,10 +1267,9 @@ static int bump_unix_max_dgram_qlen(void) {
|
||||
unsigned long v;
|
||||
int r;
|
||||
|
||||
/* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
|
||||
* default of 16 is simply too low. We set the value really
|
||||
* really early during boot, so that it is actually applied to
|
||||
* all our sockets, including the $NOTIFY_SOCKET one. */
|
||||
/* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value
|
||||
* really really early during boot, so that it is actually applied to all our sockets, including the
|
||||
* $NOTIFY_SOCKET one. */
|
||||
|
||||
r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
|
||||
if (r < 0)
|
||||
@@ -1281,16 +1277,12 @@ static int bump_unix_max_dgram_qlen(void) {
|
||||
|
||||
r = safe_atolu(qlen, &v);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
|
||||
return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen);
|
||||
|
||||
if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
|
||||
return 0;
|
||||
|
||||
qlen = mfree(qlen);
|
||||
if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0);
|
||||
r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
|
||||
if (r < 0)
|
||||
return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
|
||||
@@ -1934,12 +1926,9 @@ static int do_queue_default_job(
|
||||
}
|
||||
|
||||
static void free_arguments(void) {
|
||||
size_t j;
|
||||
|
||||
/* Frees all arg_* variables, with the exception of arg_serialization */
|
||||
|
||||
for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
|
||||
arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
|
||||
rlimit_free_all(arg_default_rlimit);
|
||||
|
||||
arg_default_unit = mfree(arg_default_unit);
|
||||
arg_confirm_spawn = mfree(arg_confirm_spawn);
|
||||
@@ -2136,7 +2125,6 @@ static bool early_skip_setup_check(int argc, char *argv[]) {
|
||||
* anyway, even if in that case we also do deserialization. */
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
if (streq(argv[i], "--switched-root"))
|
||||
return false; /* If we switched root, don't skip the setup. */
|
||||
else if (streq(argv[i], "--deserialize"))
|
||||
@@ -2188,8 +2176,8 @@ int main(int argc, char *argv[]) {
|
||||
/* Disable the umask logic */
|
||||
umask(0);
|
||||
|
||||
/* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be activated
|
||||
* yet (even though the log socket for it exists). */
|
||||
/* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be
|
||||
* activated yet (even though the log socket for it exists). */
|
||||
log_set_prohibit_ipc(true);
|
||||
|
||||
/* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
|
||||
@@ -2197,62 +2185,70 @@ int main(int argc, char *argv[]) {
|
||||
* child process right before execve()'ing the actual binary, at a point in time where socket
|
||||
* activation stderr/stdout area already set up. */
|
||||
log_set_always_reopen_console(true);
|
||||
}
|
||||
|
||||
if (getpid_cached() == 1 && detect_container() <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
|
||||
/* Running outside of a container as PID 1 */
|
||||
arg_system = true;
|
||||
log_set_target(LOG_TARGET_KMSG);
|
||||
log_open();
|
||||
/* Running outside of a container as PID 1 */
|
||||
arg_system = true;
|
||||
log_set_target(LOG_TARGET_KMSG);
|
||||
log_open();
|
||||
|
||||
if (in_initrd())
|
||||
initrd_timestamp = userspace_timestamp;
|
||||
if (in_initrd())
|
||||
initrd_timestamp = userspace_timestamp;
|
||||
|
||||
if (!skip_setup) {
|
||||
r = mount_setup_early();
|
||||
if (r < 0) {
|
||||
error_message = "Failed to mount early API filesystems";
|
||||
if (!skip_setup) {
|
||||
r = mount_setup_early();
|
||||
if (r < 0) {
|
||||
error_message = "Failed to mount early API filesystems";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = initialize_security(
|
||||
&loaded_policy,
|
||||
&security_start_timestamp,
|
||||
&security_finish_timestamp,
|
||||
&error_message);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (mac_selinux_init() < 0) {
|
||||
error_message = "Failed to initialize SELinux policy";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = initialize_security(
|
||||
&loaded_policy,
|
||||
&security_start_timestamp,
|
||||
&security_finish_timestamp,
|
||||
&error_message);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (!skip_setup)
|
||||
initialize_clock();
|
||||
|
||||
/* Set the default for later on, but don't actually open the logs like this for now. Note that
|
||||
* if we are transitioning from the initrd there might still be journal fd open, and we
|
||||
* shouldn't attempt opening that before we parsed /proc/cmdline which might redirect output
|
||||
* elsewhere. */
|
||||
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
|
||||
|
||||
} else {
|
||||
/* Running inside a container, as PID 1 */
|
||||
arg_system = true;
|
||||
log_set_target(LOG_TARGET_CONSOLE);
|
||||
log_open();
|
||||
|
||||
/* For later on, see above... */
|
||||
log_set_target(LOG_TARGET_JOURNAL);
|
||||
|
||||
/* clear the kernel timestamp,
|
||||
* because we are in a container */
|
||||
kernel_timestamp = DUAL_TIMESTAMP_NULL;
|
||||
}
|
||||
|
||||
if (mac_selinux_init() < 0) {
|
||||
error_message = "Failed to initialize SELinux policy";
|
||||
initialize_coredump(skip_setup);
|
||||
|
||||
r = fixup_environment();
|
||||
if (r < 0) {
|
||||
log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
|
||||
error_message = "Failed to fix up PID1 environment";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!skip_setup)
|
||||
initialize_clock();
|
||||
|
||||
/* Set the default for later on, but don't actually
|
||||
* open the logs like this for now. Note that if we
|
||||
* are transitioning from the initrd there might still
|
||||
* be journal fd open, and we shouldn't attempt
|
||||
* opening that before we parsed /proc/cmdline which
|
||||
* might redirect output elsewhere. */
|
||||
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
|
||||
|
||||
} else if (getpid_cached() == 1) {
|
||||
/* Running inside a container, as PID 1 */
|
||||
arg_system = true;
|
||||
log_set_target(LOG_TARGET_CONSOLE);
|
||||
log_open();
|
||||
|
||||
/* For later on, see above... */
|
||||
log_set_target(LOG_TARGET_JOURNAL);
|
||||
|
||||
/* clear the kernel timestamp,
|
||||
* because we are in a container */
|
||||
kernel_timestamp = DUAL_TIMESTAMP_NULL;
|
||||
} else {
|
||||
/* Running as user instance */
|
||||
arg_system = false;
|
||||
@@ -2264,24 +2260,14 @@ int main(int argc, char *argv[]) {
|
||||
kernel_timestamp = DUAL_TIMESTAMP_NULL;
|
||||
}
|
||||
|
||||
initialize_coredump(skip_setup);
|
||||
|
||||
r = fixup_environment();
|
||||
if (r < 0) {
|
||||
log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
|
||||
error_message = "Failed to fix up PID1 environment";
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (arg_system) {
|
||||
|
||||
/* Try to figure out if we can use colors with the console. No
|
||||
* need to do that for user instances since they never log
|
||||
* into the console. */
|
||||
/* Try to figure out if we can use colors with the console. No need to do that for user instances since
|
||||
* they never log into the console. */
|
||||
log_show_color(colors_enabled());
|
||||
|
||||
r = make_null_stdio();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
|
||||
log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m");
|
||||
}
|
||||
|
||||
/* Mount /proc, /sys and friends, so that /proc/cmdline and
|
||||
@@ -2429,10 +2415,10 @@ int main(int argc, char *argv[]) {
|
||||
finish:
|
||||
pager_close();
|
||||
|
||||
if (m)
|
||||
if (m) {
|
||||
arg_shutdown_watchdog = m->shutdown_watchdog;
|
||||
|
||||
m = manager_free(m);
|
||||
m = manager_free(m);
|
||||
}
|
||||
|
||||
free_arguments();
|
||||
mac_selinux_finish();
|
||||
@@ -2465,7 +2451,6 @@ finish:
|
||||
|
||||
if (shutdown_verb) {
|
||||
r = become_shutdown(shutdown_verb, retval);
|
||||
|
||||
log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
|
||||
error_message = "Failed to execute shutdown binary";
|
||||
}
|
||||
|
||||
@@ -315,7 +315,14 @@ static void test_fd_duplicate_data_fd(void) {
|
||||
assert_se(read(fd2, &j, sizeof(j)) == 0);
|
||||
}
|
||||
|
||||
static void test_read_nr_open(void) {
|
||||
log_info("nr-open: %i", read_nr_open());
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
|
||||
test_close_many();
|
||||
test_close_nointr();
|
||||
test_same_fd();
|
||||
@@ -324,6 +331,7 @@ int main(int argc, char *argv[]) {
|
||||
test_fd_move_above_stdio();
|
||||
test_rearrange_stdio();
|
||||
test_fd_duplicate_data_fd();
|
||||
test_read_nr_open();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user