2020-11-09 13:23:58 +09:00
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2015-04-10 19:10:00 +02:00
2019-10-31 11:07:23 +09:00
# include <fcntl.h>
2021-09-30 11:19:34 +02:00
# include <linux/oom.h>
2023-02-08 18:01:26 +01:00
# include <pthread.h>
2016-06-14 23:52:29 +02:00
# include <sys/mount.h>
2016-02-22 18:36:54 +01:00
# include <sys/personality.h>
2016-06-14 23:52:29 +02:00
# include <sys/prctl.h>
2015-04-10 19:10:00 +02:00
# include <sys/stat.h>
2015-10-24 22:58:24 +02:00
# include <sys/types.h>
2015-04-10 19:10:00 +02:00
# include <sys/wait.h>
# include <unistd.h>
2017-10-03 10:41:51 +02:00
# if HAVE_VALGRIND_VALGRIND_H
2016-06-19 23:43:35 +00:00
# include <valgrind/valgrind.h>
# endif
2015-04-10 19:10:00 +02:00
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2016-02-22 18:36:54 +01:00
# include "architecture.h"
2021-04-01 16:46:01 +02:00
# include "dirent-util.h"
2021-07-07 15:57:51 +02:00
# include "errno-list.h"
# include "errno-util.h"
2016-06-14 23:52:29 +02:00
# include "fd-util.h"
2021-11-24 15:24:55 +01:00
# include "ioprio-util.h"
2015-04-10 19:10:00 +02:00
# include "log.h"
# include "macro.h"
2019-10-31 11:07:23 +09:00
# include "missing_sched.h"
# include "missing_syscall.h"
2023-03-13 15:22:38 +01:00
# include "namespace-util.h"
2016-06-12 19:51:11 -04:00
# include "parse-util.h"
2015-10-24 22:58:24 +02:00
# include "process-util.h"
2021-07-07 15:57:51 +02:00
# include "procfs-util.h"
2020-01-02 17:33:51 +01:00
# include "rlimit-util.h"
2017-12-22 13:08:14 +01:00
# include "signal-util.h"
2016-06-12 19:42:51 -04:00
# include "stdio-util.h"
2015-10-24 22:58:24 +02:00
# include "string-util.h"
2015-04-10 23:15:59 +02:00
# include "terminal-util.h"
2018-09-13 14:31:13 +02:00
# include "tests.h"
2020-01-02 17:33:51 +01:00
# include "user-util.h"
2015-10-24 22:58:24 +02:00
# include "virt.h"
2015-04-10 19:10:00 +02:00
2023-10-17 10:16:31 +02:00
static void test_pid_get_comm_one ( pid_t pid ) {
2015-04-10 19:10:00 +02:00
struct stat st ;
2016-07-18 22:31:34 +02:00
_cleanup_free_ char * a = NULL , * c = NULL , * d = NULL , * f = NULL , * i = NULL ;
2015-04-10 19:10:00 +02:00
_cleanup_free_ char * env = NULL ;
2017-12-14 19:02:29 +01:00
char path [ STRLEN ( " /proc//comm " ) + DECIMAL_STR_MAX ( pid_t ) ] ;
2015-04-10 19:10:00 +02:00
pid_t e ;
uid_t u ;
gid_t g ;
dev_t h ;
int r ;
2021-04-02 11:35:23 +02:00
log_info ( " /* %s */ " , __func__ ) ;
2016-06-12 19:42:51 -04:00
xsprintf ( path , " /proc/ " PID_FMT " /comm " , pid ) ;
if ( stat ( path , & st ) = = 0 ) {
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_comm ( pid , & a ) ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " comm: '%s' " , pid , a ) ;
2015-04-29 21:40:54 +02:00
} else
2016-06-12 19:42:51 -04:00
log_warning ( " %s not exist. " , path ) ;
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( pid , 0 , PROCESS_CMDLINE_COMM_FALLBACK , & c ) ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " cmdline: '%s' " , pid , c ) ;
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( pid , 8 , 0 , & d ) ) ;
2016-06-14 23:52:29 +02:00
log_info ( " PID " PID_FMT " cmdline truncated to 8: '%s' " , pid , d ) ;
free ( d ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( pid , 1 , 0 , & d ) ) ;
2016-06-14 23:52:29 +02:00
log_info ( " PID " PID_FMT " cmdline truncated to 1: '%s' " , pid , d ) ;
2015-04-10 19:10:00 +02:00
2021-07-07 15:57:51 +02:00
r = get_process_ppid ( pid , & e ) ;
2024-09-19 11:39:09 +02:00
if ( pid = = 1 )
ASSERT_ERROR ( r , EADDRNOTAVAIL ) ;
else
ASSERT_OK ( r ) ;
2021-07-07 15:57:51 +02:00
if ( r > = 0 ) {
log_info ( " PID " PID_FMT " PPID: " PID_FMT , pid , e ) ;
2024-09-19 11:39:09 +02:00
ASSERT_GT ( e , 0 ) ;
2021-07-07 15:57:51 +02:00
}
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_TRUE ( pid_is_kernel_thread ( pid ) = = 0 | | pid ! = 1 ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
r = get_process_exe ( pid , & f ) ;
2024-09-19 11:39:09 +02:00
if ( r ! = - EACCES )
ASSERT_OK ( r ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " exe: '%s' " , pid , strna ( f ) ) ;
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( pid_get_uid ( pid , & u ) ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " UID: " UID_FMT , pid , u ) ;
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( get_process_gid ( pid , & g ) ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " GID: " GID_FMT , pid , g ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
r = get_process_environ ( pid , & env ) ;
2024-09-19 11:39:09 +02:00
if ( r ! = - EACCES )
ASSERT_OK ( r ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " strlen(environ): %zi " , pid , env ? ( ssize_t ) strlen ( env ) : ( ssize_t ) - errno ) ;
2015-04-10 19:10:00 +02:00
2024-09-19 11:39:09 +02:00
if ( ! detect_container ( ) & & pid = = 1 )
ASSERT_ERROR ( get_ctty_devnr ( pid , & h ) , ENXIO ) ;
2015-04-10 19:10:00 +02:00
2018-02-16 07:03:13 +01:00
( void ) getenv_for_pid ( pid , " PATH " , & i ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " $PATH: '%s' " , pid , strna ( i ) ) ;
2015-04-10 19:10:00 +02:00
}
2023-10-17 10:16:31 +02:00
TEST ( pid_get_comm ) {
2021-11-24 12:11:17 +01:00
if ( saved_argc > 1 ) {
pid_t pid = 0 ;
( void ) parse_pid ( saved_argv [ 1 ] , & pid ) ;
2023-10-17 10:16:31 +02:00
test_pid_get_comm_one ( pid ) ;
2021-11-24 12:11:17 +01:00
} else {
2023-10-17 10:16:31 +02:00
TEST_REQ_RUNNING_SYSTEMD ( test_pid_get_comm_one ( 1 ) ) ;
test_pid_get_comm_one ( getpid ( ) ) ;
2021-11-24 12:11:17 +01:00
}
}
2023-10-16 23:17:29 +02:00
static void test_pid_get_cmdline_one ( pid_t pid ) {
2023-03-23 01:05:38 +09:00
_cleanup_free_ char * c = NULL , * d = NULL , * e = NULL , * f = NULL , * g = NULL , * h = NULL , * joined = NULL ;
_cleanup_strv_free_ char * * strv_a = NULL , * * strv_b = NULL ;
2021-04-01 16:46:01 +02:00
int r ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , 0 , & c ) ;
2021-04-01 16:46:01 +02:00
log_info ( " PID " PID_FMT " : %s " , pid , r > = 0 ? c : errno_to_name ( r ) ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & d ) ;
2021-04-01 16:46:01 +02:00
log_info ( " %s " , r > = 0 ? d : errno_to_name ( r ) ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_QUOTE , & e ) ;
2021-04-01 16:46:01 +02:00
log_info ( " %s " , r > = 0 ? e : errno_to_name ( r ) ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_COMM_FALLBACK , & f ) ;
2021-04-01 16:46:01 +02:00
log_info ( " %s " , r > = 0 ? f : errno_to_name ( r ) ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_QUOTE_POSIX , & g ) ;
2021-04-01 16:46:01 +02:00
log_info ( " %s " , r > = 0 ? g : errno_to_name ( r ) ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_QUOTE_POSIX | PROCESS_CMDLINE_COMM_FALLBACK , & h ) ;
2021-04-01 16:46:01 +02:00
log_info ( " %s " , r > = 0 ? h : errno_to_name ( r ) ) ;
2023-03-23 01:05:38 +09:00
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline_strv ( pid , 0 , & strv_a ) ;
2023-03-23 01:05:38 +09:00
if ( r > = 0 )
2024-09-19 11:39:09 +02:00
ASSERT_NOT_NULL ( joined = strv_join ( strv_a , " \" , \" " ) ) ;
2023-03-23 01:05:38 +09:00
log_info ( " \" %s \" " , r > = 0 ? joined : errno_to_name ( r ) ) ;
joined = mfree ( joined ) ;
2023-10-16 23:17:29 +02:00
r = pid_get_cmdline_strv ( pid , PROCESS_CMDLINE_COMM_FALLBACK , & strv_b ) ;
2023-03-23 01:05:38 +09:00
if ( r > = 0 )
2024-09-19 11:39:09 +02:00
ASSERT_NOT_NULL ( joined = strv_join ( strv_b , " \" , \" " ) ) ;
2023-03-23 01:05:38 +09:00
log_info ( " \" %s \" " , r > = 0 ? joined : errno_to_name ( r ) ) ;
2021-04-01 16:46:01 +02:00
}
2023-10-16 23:17:29 +02:00
TEST ( pid_get_cmdline ) {
2021-04-01 16:46:01 +02:00
_cleanup_closedir_ DIR * d = NULL ;
2023-10-17 13:43:59 +02:00
int r ;
2021-04-01 16:46:01 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( proc_dir_open ( & d ) ) ;
2021-04-01 16:46:01 +02:00
2023-10-17 13:43:59 +02:00
for ( ; ; ) {
2021-04-01 16:46:01 +02:00
pid_t pid ;
2023-10-17 13:43:59 +02:00
r = proc_dir_read ( d , & pid ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2021-04-01 16:46:01 +02:00
2023-10-17 13:43:59 +02:00
if ( r = = 0 ) /* EOF */
break ;
2021-04-01 16:46:01 +02:00
2023-10-16 23:17:29 +02:00
test_pid_get_cmdline_one ( pid ) ;
2021-04-01 16:46:01 +02:00
}
}
2023-10-17 10:16:31 +02:00
static void test_pid_get_comm_escape_one ( const char * input , const char * output ) {
2018-05-16 21:50:35 -04:00
_cleanup_free_ char * n = NULL ;
2021-04-02 11:35:23 +02:00
log_debug ( " input: <%s> — output: <%s> " , input , output ) ;
2018-05-16 21:50:35 -04:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( prctl ( PR_SET_NAME , input ) ) ;
ASSERT_OK ( pid_get_comm ( 0 , & n ) ) ;
2018-05-16 21:50:35 -04:00
2021-04-02 11:35:23 +02:00
log_debug ( " got: <%s> " , n ) ;
2018-05-16 21:50:35 -04:00
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( n , output ) ;
2018-05-16 21:50:35 -04:00
}
2023-10-17 10:16:31 +02:00
TEST ( pid_get_comm_escape ) {
2018-05-16 21:50:35 -04:00
_cleanup_free_ char * saved = NULL ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_comm ( 0 , & saved ) ) ;
2023-10-17 10:16:31 +02:00
test_pid_get_comm_escape_one ( " " , " " ) ;
test_pid_get_comm_escape_one ( " foo " , " foo " ) ;
test_pid_get_comm_escape_one ( " 012345678901234 " , " 012345678901234 " ) ;
test_pid_get_comm_escape_one ( " 0123456789012345 " , " 012345678901234 " ) ;
test_pid_get_comm_escape_one ( " äöüß " , " \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
test_pid_get_comm_escape_one ( " xäöüß " , " x \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
test_pid_get_comm_escape_one ( " xxäöüß " , " xx \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
test_pid_get_comm_escape_one ( " xxxäöüß " , " xxx \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
test_pid_get_comm_escape_one ( " xxxxäöüß " , " xxxx \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
test_pid_get_comm_escape_one ( " xxxxxäöüß " , " xxxxx \\ 303 \\ 244 \\ 303 \\ 266 \\ 303 \\ 274 \\ 303 \\ 237 " ) ;
2018-05-16 21:50:35 -04:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( prctl ( PR_SET_NAME , saved ) ) ;
2018-05-16 21:50:35 -04:00
}
2021-11-24 12:11:17 +01:00
TEST ( pid_is_unwaited ) {
2015-04-10 19:10:00 +02:00
pid_t pid ;
pid = fork ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( pid ) ;
2015-04-10 19:10:00 +02:00
if ( pid = = 0 ) {
_exit ( EXIT_SUCCESS ) ;
} else {
int status ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( waitpid ( pid , & status , 0 ) , pid ) ;
ASSERT_OK_ZERO ( pid_is_unwaited ( pid ) ) ;
2015-04-10 19:10:00 +02:00
}
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( pid_is_unwaited ( getpid_cached ( ) ) ) ;
ASSERT_FAIL ( pid_is_unwaited ( - 1 ) ) ;
2015-04-10 19:10:00 +02:00
}
2021-11-24 12:11:17 +01:00
TEST ( pid_is_alive ) {
2015-04-10 19:10:00 +02:00
pid_t pid ;
pid = fork ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( pid ) ;
2015-04-10 19:10:00 +02:00
if ( pid = = 0 ) {
_exit ( EXIT_SUCCESS ) ;
} else {
int status ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( waitpid ( pid , & status , 0 ) , pid ) ;
ASSERT_OK_ZERO ( pid_is_alive ( pid ) ) ;
2015-04-10 19:10:00 +02:00
}
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( pid_is_alive ( getpid_cached ( ) ) ) ;
ASSERT_FAIL ( pid_is_alive ( - 1 ) ) ;
2015-04-10 19:10:00 +02:00
}
2021-11-24 12:11:17 +01:00
TEST ( personality ) {
2024-09-19 11:39:09 +02:00
ASSERT_NOT_NULL ( personality_to_string ( PER_LINUX ) ) ;
ASSERT_NULL ( personality_to_string ( PERSONALITY_INVALID ) ) ;
2016-02-22 18:36:54 +01:00
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( personality_to_string ( PER_LINUX ) , architecture_to_string ( native_architecture ( ) ) ) ;
2016-02-22 18:36:54 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( personality_from_string ( personality_to_string ( PER_LINUX ) ) , ( unsigned long ) PER_LINUX ) ;
ASSERT_EQ ( personality_from_string ( architecture_to_string ( native_architecture ( ) ) ) , ( unsigned long ) PER_LINUX ) ;
2016-02-22 18:36:54 +01:00
# ifdef __x86_64__
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( personality_to_string ( PER_LINUX ) , " x86-64 " ) ;
ASSERT_STREQ ( personality_to_string ( PER_LINUX32 ) , " x86 " ) ;
2016-02-22 18:36:54 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( personality_from_string ( " x86-64 " ) , ( unsigned long ) PER_LINUX ) ;
ASSERT_EQ ( personality_from_string ( " x86 " ) , ( unsigned long ) PER_LINUX32 ) ;
ASSERT_EQ ( personality_from_string ( " ia64 " ) , PERSONALITY_INVALID ) ;
ASSERT_EQ ( personality_from_string ( NULL ) , PERSONALITY_INVALID ) ;
2016-02-22 18:36:54 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( personality_from_string ( personality_to_string ( PER_LINUX32 ) ) , ( unsigned long ) PER_LINUX32 ) ;
2016-02-22 18:36:54 +01:00
# endif
}
2023-10-16 23:17:29 +02:00
TEST ( pid_get_cmdline_harder ) {
2016-06-14 23:52:29 +02:00
char path [ ] = " /tmp/test-cmdlineXXXXXX " ;
2022-12-19 13:07:42 +01:00
_cleanup_close_ int fd = - EBADF ;
2016-06-14 23:52:29 +02:00
_cleanup_free_ char * line = NULL ;
2023-03-23 01:05:38 +09:00
_cleanup_strv_free_ char * * args = NULL ;
2016-06-14 23:52:29 +02:00
pid_t pid ;
2023-03-13 15:22:38 +01:00
int r ;
2016-06-14 23:52:29 +02:00
2018-09-20 16:09:05 +09:00
if ( geteuid ( ) ! = 0 ) {
log_info ( " Skipping %s: not root " , __func__ ) ;
2016-06-14 23:52:29 +02:00
return ;
2018-09-20 16:09:05 +09:00
}
2016-06-14 23:52:29 +02:00
2018-10-24 16:53:14 +02:00
if ( ! have_namespaces ( ) ) {
log_notice ( " Testing without namespaces, skipping %s " , __func__ ) ;
return ;
}
2017-10-03 10:41:51 +02:00
# if HAVE_VALGRIND_VALGRIND_H
2016-06-19 23:43:35 +00:00
/* valgrind patches open(/proc//cmdline)
2023-10-16 23:17:29 +02:00
* so , test_pid_get_cmdline_harder fails always
2016-06-19 23:43:35 +00:00
* See https : //github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
2018-09-20 16:09:05 +09:00
if ( RUNNING_ON_VALGRIND ) {
log_info ( " Skipping %s: running on valgrind " , __func__ ) ;
2016-06-19 23:43:35 +00:00
return ;
2018-09-20 16:09:05 +09:00
}
2016-06-19 23:43:35 +00:00
# endif
2016-06-14 23:52:29 +02:00
pid = fork ( ) ;
if ( pid > 0 ) {
siginfo_t si ;
( void ) wait_for_terminate ( pid , & si ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( si . si_code , CLD_EXITED ) ;
ASSERT_OK_ZERO ( si . si_status ) ;
2016-06-14 23:52:29 +02:00
return ;
}
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( pid ) ;
2016-06-14 23:52:29 +02:00
2023-03-13 15:22:38 +01:00
r = detach_mount_namespace ( ) ;
if ( r < 0 ) {
log_warning_errno ( r , " detach mount namespace failed: %m " ) ;
2024-09-19 11:39:09 +02:00
if ( ! ERRNO_IS_PRIVILEGE ( r ) )
ASSERT_OK ( r ) ;
2018-07-19 10:24:07 +00:00
return ;
}
2018-03-09 01:10:42 +00:00
2016-06-14 23:52:29 +02:00
fd = mkostemp ( path , O_CLOEXEC ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( fd ) ;
2016-11-17 20:57:22 -05:00
2018-07-19 10:24:07 +00:00
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its / proc / PID / hierarchy automatically as soon as the test stops . */
2016-11-17 20:57:22 -05:00
if ( mount ( path , " /proc/self/cmdline " , " bind " , MS_BIND , NULL ) < 0 ) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno ( errno , " mount(..., \" /proc/self/cmdline \" , \" bind \" , ...) failed: %m " ) ;
2024-09-19 11:39:09 +02:00
ASSERT_TRUE ( IN_SET ( errno , EPERM , EACCES ) ) ;
2016-11-17 20:57:22 -05:00
return ;
}
2023-07-28 05:55:42 +09:00
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
2021-03-23 00:49:28 -07:00
* the cmdline . */
if ( setrlimit ( RLIMIT_STACK , & RLIMIT_MAKE_CONST ( RLIM_INFINITY ) ) < 0 )
log_warning ( " Testing without RLIMIT_STACK=infinity " ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( unlink ( path ) ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( prctl ( PR_SET_NAME , " testa " ) ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_ERROR ( pid_get_cmdline ( 0 , SIZE_MAX , 0 , & line ) , ENOENT ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [testa] " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " \" [testa] \" " ) ; /* quoting is enabled here */
2021-03-30 19:42:36 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 0 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 1 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " … " ) ;
Rework cmdline printing to use unicode
The functions to retrieve and print process cmdlines were based on the
assumption that they contain printable ASCII, and everything else
should be filtered out. That assumption doesn't hold in today's world,
where people are free to use unicode everywhere.
This replaces the custom cmdline reading code with a more generic approach
using utf8_escape_non_printable_full().
For kernel threads, truncation is done on the parenthesized name, so we'll
get "[worker]", "[worker…]", …, "[w…]", "[…", "…" as we reduce the number of
available columns.
This implementation is most likely slower for very long cmdlines, but I don't
think this is very important. The common case is to have short commandlines,
and should print those properly. Absurdly long cmdlines are the exception,
which needs to be handled correctly and safely, but speed is not too important.
Fixes #12532.
v2:
- use size_t for the number of columns. This change propagates into various
other functions that call get_process_cmdline(), increasing the size of the
patch, but the changes are rather trivial.
2019-05-15 11:20:26 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 2 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 3 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [t… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 4 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [te… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 5 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [tes… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 6 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [test… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 7 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [testa] " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 8 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [testa] " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , PROCESS_CMDLINE_COMM_FALLBACK , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , STRV_MAKE ( " [testa] " ) ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2021-03-30 19:42:36 +02:00
/* Test with multiple arguments that don't require quoting */
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( write ( fd , " foo \0 bar " , 8 ) , 8 ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , 0 , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , PROCESS_CMDLINE_COMM_FALLBACK , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , STRV_MAKE ( " foo " , " bar " ) ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( write ( fd , " quux " , 4 ) , 4 ) ;
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , 0 , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 1 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " … " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 2 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " f… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 3 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " fo… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 4 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 5 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo … " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 6 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo b… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 7 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo ba… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 8 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 9 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar … " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 10 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar q… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 11 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar qu… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 12 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 13 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 14 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 1000 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " foo bar quux " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , PROCESS_CMDLINE_COMM_FALLBACK , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , STRV_MAKE ( " foo " , " bar " , " quux " ) ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( ftruncate ( fd , 0 ) ) ;
ASSERT_OK_ERRNO ( prctl ( PR_SET_NAME , " aaaa bbbb cccc " ) ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_ERROR ( pid_get_cmdline ( 0 , SIZE_MAX , 0 , & line ) , ENOENT ) ;
2016-06-14 23:52:29 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [aaaa bbbb cccc] " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 10 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [aaaa bbb… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 11 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [aaaa bbbb… " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , 12 , PROCESS_CMDLINE_COMM_FALLBACK , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " '%s' " , line ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , " [aaaa bbbb … " ) ;
2016-06-14 23:52:29 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , PROCESS_CMDLINE_COMM_FALLBACK , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , STRV_MAKE ( " [aaaa bbbb cccc] " ) ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2021-03-30 19:42:36 +02:00
/* Test with multiple arguments that do require quoting */
# define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
2021-11-01 09:01:40 +09:00
# define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
2023-03-23 01:05:38 +09:00
# define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
# define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO_ERRNO ( lseek ( fd , SEEK_SET , 0 ) ) ;
ASSERT_OK_EQ_ERRNO ( write ( fd , CMDLINE1 , sizeof ( CMDLINE1 ) ) , ( ssize_t ) sizeof ( CMDLINE1 ) ) ;
ASSERT_OK_ZERO_ERRNO ( ftruncate ( fd , sizeof ( CMDLINE1 ) ) ) ;
2021-03-30 19:42:36 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_QUOTE , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " got: ==%s== " , line ) ;
log_debug ( " exp: ==%s== " , EXPECT1 ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , EXPECT1 ) ;
2021-03-30 19:42:36 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_QUOTE_POSIX , & line ) ) ;
2021-03-11 00:10:02 +01:00
log_debug ( " got: ==%s== " , line ) ;
log_debug ( " exp: ==%s== " , EXPECT1p ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , EXPECT1p ) ;
2021-03-11 00:10:02 +01:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , 0 , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , EXPECT1v ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2021-03-30 19:42:36 +02:00
# define CMDLINE2 "foo\0\1\2\3\0\0"
2021-11-01 09:01:40 +09:00
# define EXPECT2 "foo \"\\001\\002\\003\""
2023-03-23 01:05:38 +09:00
# define EXPECT2p "foo $'\\001\\002\\003'"
# define EXPECT2v STRV_MAKE("foo", "\1\2\3")
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO_ERRNO ( lseek ( fd , SEEK_SET , 0 ) ) ;
ASSERT_OK_EQ_ERRNO ( write ( fd , CMDLINE2 , sizeof ( CMDLINE2 ) ) , ( ssize_t ) sizeof ( CMDLINE2 ) ) ;
ASSERT_OK_ZERO_ERRNO ( ftruncate ( fd , sizeof CMDLINE2 ) ) ;
2021-03-30 19:42:36 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_QUOTE , & line ) ) ;
2021-04-02 11:35:23 +02:00
log_debug ( " got: ==%s== " , line ) ;
log_debug ( " exp: ==%s== " , EXPECT2 ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , EXPECT2 ) ;
2021-03-30 19:42:36 +02:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( 0 , SIZE_MAX , PROCESS_CMDLINE_QUOTE_POSIX , & line ) ) ;
2021-03-11 00:10:02 +01:00
log_debug ( " got: ==%s== " , line ) ;
log_debug ( " exp: ==%s== " , EXPECT2p ) ;
2024-04-10 13:19:39 +02:00
ASSERT_STREQ ( line , EXPECT2p ) ;
2021-03-11 00:10:02 +01:00
line = mfree ( line ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline_strv ( 0 , 0 , & args ) ) ;
ASSERT_TRUE ( strv_equal ( args , EXPECT2v ) ) ;
2023-03-23 01:05:38 +09:00
args = strv_free ( args ) ;
2016-06-14 23:52:29 +02:00
safe_close ( fd ) ;
2017-12-22 13:24:40 +01:00
_exit ( EXIT_SUCCESS ) ;
2016-06-14 23:52:29 +02:00
}
2021-11-24 12:11:17 +01:00
TEST ( getpid_cached ) {
2017-07-20 15:46:05 +02:00
siginfo_t si ;
pid_t a , b , c , d , e , f , child ;
a = raw_getpid ( ) ;
b = getpid_cached ( ) ;
c = getpid ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( a , b ) ;
ASSERT_EQ ( a , c ) ;
2017-07-20 15:46:05 +02:00
child = fork ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( child ) ;
2017-07-20 15:46:05 +02:00
if ( child = = 0 ) {
/* In child */
a = raw_getpid ( ) ;
b = getpid_cached ( ) ;
c = getpid ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( a , b ) ;
ASSERT_EQ ( a , c ) ;
2017-12-22 13:24:40 +01:00
_exit ( EXIT_SUCCESS ) ;
2017-07-20 15:46:05 +02:00
}
d = raw_getpid ( ) ;
e = getpid_cached ( ) ;
f = getpid ( ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( a , d ) ;
ASSERT_EQ ( a , e ) ;
ASSERT_EQ ( a , f ) ;
2017-07-20 15:46:05 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( wait_for_terminate ( child , & si ) ) ;
ASSERT_EQ ( si . si_status , 0 ) ;
ASSERT_EQ ( si . si_code , CLD_EXITED ) ;
2017-07-20 15:46:05 +02:00
}
2021-11-24 12:11:17 +01:00
TEST ( getpid_measure ) {
2017-07-20 15:46:05 +02:00
usec_t t , q ;
2021-04-02 11:44:48 +02:00
unsigned long long iterations = slow_tests_enabled ( ) ? 1000000 : 1000 ;
log_info ( " /* %s (%llu iterations) */ " , __func__ , iterations ) ;
2021-04-02 11:35:23 +02:00
2017-07-20 15:46:05 +02:00
t = now ( CLOCK_MONOTONIC ) ;
2021-04-02 11:44:48 +02:00
for ( unsigned long long i = 0 ; i < iterations ; i + + )
2017-07-20 15:46:05 +02:00
( void ) getpid ( ) ;
q = now ( CLOCK_MONOTONIC ) - t ;
2023-07-10 14:54:11 +02:00
log_info ( " glibc getpid(): %lf μs each " , ( double ) q / iterations ) ;
2021-04-02 11:44:48 +02:00
iterations * = 50 ; /* _cached() is about 50 times faster, so we need more iterations */
2017-07-20 15:46:05 +02:00
t = now ( CLOCK_MONOTONIC ) ;
2021-04-02 11:44:48 +02:00
for ( unsigned long long i = 0 ; i < iterations ; i + + )
2017-07-20 15:46:05 +02:00
( void ) getpid_cached ( ) ;
q = now ( CLOCK_MONOTONIC ) - t ;
2023-07-10 14:54:11 +02:00
log_info ( " getpid_cached(): %lf μs each " , ( double ) q / iterations ) ;
2017-07-20 15:46:05 +02:00
}
2021-11-24 12:11:17 +01:00
TEST ( safe_fork ) {
2017-12-22 13:08:14 +01:00
siginfo_t status ;
pid_t pid ;
int r ;
BLOCK_SIGNALS ( SIGCHLD ) ;
2023-11-02 11:04:36 +01:00
r = safe_fork ( " (test-child) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_DEATHSIG_SIGTERM | FORK_REARRANGE_STDIO | FORK_REOPEN_LOG , & pid ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2017-12-22 13:08:14 +01:00
if ( r = = 0 ) {
/* child */
2023-06-01 08:31:25 +09:00
usleep_safe ( 100 * USEC_PER_MSEC ) ;
2017-12-22 13:08:14 +01:00
_exit ( 88 ) ;
}
2024-09-19 11:39:09 +02:00
ASSERT_OK ( wait_for_terminate ( pid , & status ) ) ;
ASSERT_EQ ( status . si_code , CLD_EXITED ) ;
ASSERT_EQ ( status . si_status , 88 ) ;
2017-12-22 13:08:14 +01:00
}
2021-11-24 12:11:17 +01:00
TEST ( pid_to_ptr ) {
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( PTR_TO_PID ( NULL ) , 0 ) ;
2024-04-08 17:12:48 +02:00
ASSERT_NULL ( PID_TO_PTR ( 0 ) ) ;
2018-01-11 16:02:47 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( 1 ) ) , 1 ) ;
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( 2 ) ) , 2 ) ;
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( - 1 ) ) , - 1 ) ;
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( - 2 ) ) , - 2 ) ;
2018-01-11 16:02:47 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( INT16_MAX ) ) , INT16_MAX ) ;
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( INT16_MIN ) ) , INT16_MIN ) ;
2018-01-11 16:02:47 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( INT32_MAX ) ) , INT32_MAX ) ;
ASSERT_EQ ( PTR_TO_PID ( PID_TO_PTR ( INT32_MIN ) ) , INT32_MIN ) ;
2018-01-11 16:02:47 +01:00
}
2021-11-24 15:52:13 +01:00
static void test_ioprio_class_from_to_string_one ( const char * val , int expected , int normalized ) {
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( ioprio_class_from_string ( val ) , expected ) ;
2018-03-16 11:15:58 +01:00
if ( expected > = 0 ) {
_cleanup_free_ char * s = NULL ;
unsigned ret ;
2021-11-24 15:52:13 +01:00
int combined ;
2018-03-16 11:15:58 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( ioprio_class_to_string_alloc ( expected , & s ) ) ;
2021-11-24 15:52:13 +01:00
/* We sometimes get a class number and sometimes a name back */
2024-09-19 11:39:09 +02:00
ASSERT_TRUE ( streq ( s , val ) | | safe_atou ( val , & ret ) = = 0 ) ;
2021-11-24 15:52:13 +01:00
/* Make sure normalization works, i.e. NONE → BE gets normalized */
combined = ioprio_normalize ( ioprio_prio_value ( expected , 0 ) ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( ioprio_prio_class ( combined ) , normalized ) ;
ASSERT_TRUE ( expected ! = IOPRIO_CLASS_NONE | | ioprio_prio_data ( combined ) = = 4 ) ;
2018-03-16 11:15:58 +01:00
}
}
2016-12-06 20:29:07 +01:00
2021-11-24 12:11:17 +01:00
TEST ( ioprio_class_from_to_string ) {
2021-11-24 15:52:13 +01:00
test_ioprio_class_from_to_string_one ( " none " , IOPRIO_CLASS_NONE , IOPRIO_CLASS_BE ) ;
test_ioprio_class_from_to_string_one ( " realtime " , IOPRIO_CLASS_RT , IOPRIO_CLASS_RT ) ;
test_ioprio_class_from_to_string_one ( " best-effort " , IOPRIO_CLASS_BE , IOPRIO_CLASS_BE ) ;
test_ioprio_class_from_to_string_one ( " idle " , IOPRIO_CLASS_IDLE , IOPRIO_CLASS_IDLE ) ;
test_ioprio_class_from_to_string_one ( " 0 " , IOPRIO_CLASS_NONE , IOPRIO_CLASS_BE ) ;
test_ioprio_class_from_to_string_one ( " 1 " , 1 , 1 ) ;
test_ioprio_class_from_to_string_one ( " 7 " , 7 , 7 ) ;
test_ioprio_class_from_to_string_one ( " 8 " , 8 , 8 ) ;
test_ioprio_class_from_to_string_one ( " 9 " , - EINVAL , - EINVAL ) ;
test_ioprio_class_from_to_string_one ( " -1 " , - EINVAL , - EINVAL ) ;
2018-03-16 11:15:58 +01:00
}
2021-11-24 12:11:17 +01:00
TEST ( setpriority_closest ) {
2020-01-02 17:33:51 +01:00
int r ;
2021-04-02 11:35:23 +02:00
r = safe_fork ( " (test-setprio) " ,
2024-09-19 12:04:34 +02:00
FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_LOG | FORK_REOPEN_LOG , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2020-01-02 17:33:51 +01:00
if ( r = = 0 ) {
bool full_test ;
int p , q ;
/* child */
/* rlimit of 30 equals nice level of -10 */
if ( setrlimit ( RLIMIT_NICE , & RLIMIT_MAKE_CONST ( 30 ) ) < 0 ) {
2020-01-08 12:12:16 +01:00
/* If this fails we are probably unprivileged or in a userns of some kind, let's skip
2020-01-02 17:33:51 +01:00
* the full test */
2024-09-19 11:39:09 +02:00
if ( ! ERRNO_IS_PRIVILEGE ( errno ) )
ASSERT_OK_ERRNO ( - 1 ) ;
2020-01-02 17:33:51 +01:00
full_test = false ;
} else {
2023-11-08 12:15:22 -07:00
/* However, if the hard limit was above 30, setrlimit would succeed unprivileged, so
* check if the UID / GID can be changed before enabling the full test . */
if ( setresgid ( GID_NOBODY , GID_NOBODY , GID_NOBODY ) < 0 ) {
2024-09-19 12:21:55 +02:00
/* If the nobody user does not exist (user namespace) we get EINVAL. */
if ( ! ERRNO_IS_PRIVILEGE ( errno ) & & errno ! = EINVAL )
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( - 1 ) ;
2023-11-08 12:15:22 -07:00
full_test = false ;
} else if ( setresuid ( UID_NOBODY , UID_NOBODY , UID_NOBODY ) < 0 ) {
2024-09-19 12:21:55 +02:00
/* If the nobody user does not exist (user namespace) we get EINVAL. */
if ( ! ERRNO_IS_PRIVILEGE ( errno ) & & errno ! = EINVAL )
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( - 1 ) ;
2023-11-08 12:15:22 -07:00
full_test = false ;
} else
full_test = true ;
2020-01-02 17:33:51 +01:00
}
errno = 0 ;
p = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
2020-01-02 17:33:51 +01:00
/* It should always be possible to set our nice level to the current one */
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( p ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( p , q ) ;
2020-01-02 17:33:51 +01:00
2020-07-07 12:08:22 +02:00
/* It should also be possible to set the nice level to one higher */
2020-01-02 17:33:51 +01:00
if ( p < PRIO_MAX - 1 ) {
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( + + p ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( p , q ) ;
2020-01-02 17:33:51 +01:00
}
2020-07-07 12:08:22 +02:00
/* It should also be possible to set the nice level to two higher */
2020-01-02 17:33:51 +01:00
if ( p < PRIO_MAX - 1 ) {
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( + + p ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( p , q ) ;
2020-01-02 17:33:51 +01:00
}
if ( full_test ) {
/* These two should work, given the RLIMIT_NICE we set above */
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( - 10 ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( q , - 10 ) ;
2020-01-02 17:33:51 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( - 9 ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( q , - 9 ) ;
2020-01-02 17:33:51 +01:00
/* This should succeed but should be clamped to the limit */
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( setpriority_closest ( - 11 ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( q , - 10 ) ;
2020-01-02 17:33:51 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( setpriority_closest ( - 8 ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( q , - 8 ) ;
2020-01-02 17:33:51 +01:00
/* This should succeed but should be clamped to the limit */
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( setpriority_closest ( - 12 ) ) ;
2020-01-02 17:33:51 +01:00
errno = 0 ;
q = getpriority ( PRIO_PROCESS , 0 ) ;
2024-09-19 11:39:09 +02:00
ASSERT_EQ ( errno , 0 ) ;
ASSERT_EQ ( q , - 10 ) ;
2020-01-02 17:33:51 +01:00
}
_exit ( EXIT_SUCCESS ) ;
}
}
2021-11-24 12:11:17 +01:00
TEST ( get_process_ppid ) {
2021-07-07 15:57:51 +02:00
uint64_t limit ;
int r ;
2024-09-19 11:39:09 +02:00
ASSERT_ERROR ( get_process_ppid ( 1 , NULL ) , EADDRNOTAVAIL ) ;
2021-07-07 15:57:51 +02:00
/* the process with the PID above the global limit definitely doesn't exist. Verify that */
2024-09-19 11:39:09 +02:00
ASSERT_OK ( procfs_get_pid_max ( & limit ) ) ;
2021-11-02 18:18:21 +01:00
log_debug ( " kernel.pid_max = % " PRIu64 , limit ) ;
if ( limit < INT_MAX ) {
r = get_process_ppid ( limit + 1 , NULL ) ;
log_debug_errno ( r , " get_process_limit(% " PRIu64 " ) → %d/%m " , limit + 1 , r ) ;
assert ( r = = - ESRCH ) ;
}
2021-07-07 15:57:51 +02:00
for ( pid_t pid = 0 ; ; ) {
_cleanup_free_ char * c1 = NULL , * c2 = NULL ;
pid_t ppid ;
r = get_process_ppid ( pid , & ppid ) ;
if ( r = = - EADDRNOTAVAIL ) {
log_info ( " No further parent PID " ) ;
break ;
}
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2021-07-07 15:57:51 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pid_get_cmdline ( pid , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & c1 ) ) ;
ASSERT_OK ( pid_get_cmdline ( ppid , SIZE_MAX , PROCESS_CMDLINE_COMM_FALLBACK , & c2 ) ) ;
2021-07-07 15:57:51 +02:00
log_info ( " Parent of " PID_FMT " (%s) is " PID_FMT " (%s). " , pid , c1 , ppid , c2 ) ;
pid = ppid ;
}
}
2021-11-24 12:11:17 +01:00
TEST ( set_oom_score_adjust ) {
2021-09-30 11:19:34 +02:00
int a , b , r ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( get_oom_score_adjust ( & a ) ) ;
2021-09-30 11:19:34 +02:00
r = set_oom_score_adjust ( OOM_SCORE_ADJ_MIN ) ;
2024-09-19 11:39:09 +02:00
if ( ! ERRNO_IS_PRIVILEGE ( r ) )
ASSERT_OK ( r ) ;
2021-09-30 11:19:34 +02:00
if ( r > = 0 ) {
2024-09-19 11:39:09 +02:00
ASSERT_OK ( get_oom_score_adjust ( & b ) ) ;
ASSERT_EQ ( b , OOM_SCORE_ADJ_MIN ) ;
2021-09-30 11:19:34 +02:00
}
2024-09-19 11:39:09 +02:00
ASSERT_OK ( set_oom_score_adjust ( a ) ) ;
ASSERT_OK ( get_oom_score_adjust ( & b ) ) ;
ASSERT_EQ ( b , a ) ;
2021-09-30 11:19:34 +02:00
}
2023-02-08 18:01:26 +01:00
static void * dummy_thread ( void * p ) {
int fd = PTR_TO_FD ( p ) ;
char x ;
/* let main thread know we are ready */
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( write ( fd , & ( const char ) { ' x ' } , 1 ) , 1 ) ;
2023-02-08 18:01:26 +01:00
/* wait for the main thread to tell us to shut down */
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( read ( fd , & x , 1 ) , 1 ) ;
2023-02-08 18:01:26 +01:00
return NULL ;
}
TEST ( get_process_threads ) {
int r ;
/* Run this test in a child, so that we can guarantee there's exactly one thread around in the child */
2024-09-19 12:04:34 +02:00
r = safe_fork ( " (nthreads) " , FORK_RESET_SIGNALS | FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_LOG , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2023-02-08 18:01:26 +01:00
if ( r = = 0 ) {
2023-10-26 18:45:33 +02:00
_cleanup_close_pair_ int pfd [ 2 ] = EBADF_PAIR , ppfd [ 2 ] = EBADF_PAIR ;
2023-02-08 18:01:26 +01:00
pthread_t t , tt ;
char x ;
2024-09-19 11:39:09 +02:00
ASSERT_OK_ERRNO ( socketpair ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , pfd ) ) ;
ASSERT_OK_ERRNO ( socketpair ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , ppfd ) ) ;
2023-02-08 18:01:26 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ ( get_process_threads ( 0 ) , 1 ) ;
ASSERT_OK_ZERO_ERRNO ( pthread_create ( & t , NULL , & dummy_thread , FD_TO_PTR ( pfd [ 0 ] ) ) ) ;
ASSERT_OK_EQ_ERRNO ( read ( pfd [ 1 ] , & x , 1 ) , 1 ) ;
ASSERT_OK_EQ ( get_process_threads ( 0 ) , 2 ) ;
ASSERT_OK_ZERO_ERRNO ( pthread_create ( & tt , NULL , & dummy_thread , FD_TO_PTR ( ppfd [ 0 ] ) ) ) ;
ASSERT_OK_EQ_ERRNO ( read ( ppfd [ 1 ] , & x , 1 ) , 1 ) ;
ASSERT_OK_EQ ( get_process_threads ( 0 ) , 3 ) ;
2023-02-08 18:01:26 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( write ( pfd [ 1 ] , & ( const char ) { ' x ' } , 1 ) , 1 ) ;
ASSERT_OK_ZERO_ERRNO ( pthread_join ( t , NULL ) ) ;
2023-02-08 18:01:26 +01:00
/* the value reported via /proc/ is decreased asynchronously, and there appears to be no nice
* way to sync on it . Hence we do the weak > = 2 check , even though = = 2 is what we ' d actually
* like to check here */
2024-09-19 11:39:09 +02:00
r = get_process_threads ( 0 ) ;
ASSERT_OK ( r ) ;
ASSERT_GE ( r , 2 ) ;
2023-02-08 18:01:26 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ_ERRNO ( write ( ppfd [ 1 ] , & ( const char ) { ' x ' } , 1 ) , 1 ) ;
ASSERT_OK_ZERO_ERRNO ( pthread_join ( tt , NULL ) ) ;
2023-02-08 18:01:26 +01:00
/* similar here */
2024-09-19 11:39:09 +02:00
r = get_process_threads ( 0 ) ;
ASSERT_OK ( r ) ;
ASSERT_GE ( r , 1 ) ;
2023-02-08 18:01:26 +01:00
_exit ( EXIT_SUCCESS ) ;
}
}
2023-06-22 11:52:06 +02:00
TEST ( is_reaper_process ) {
int r ;
2024-09-19 12:04:34 +02:00
r = safe_fork ( " (regular) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_REOPEN_LOG | FORK_WAIT , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2023-06-22 11:52:06 +02:00
if ( r = = 0 ) {
/* child */
2024-09-19 11:39:09 +02:00
ASSERT_OK_ZERO ( is_reaper_process ( ) ) ;
2023-06-22 11:52:06 +02:00
_exit ( EXIT_SUCCESS ) ;
}
2024-09-19 12:04:34 +02:00
r = safe_fork ( " (newpid) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_REOPEN_LOG | FORK_WAIT , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2023-06-22 11:52:06 +02:00
if ( r = = 0 ) {
/* child */
if ( unshare ( CLONE_NEWPID ) < 0 ) {
if ( ERRNO_IS_PRIVILEGE ( errno ) | | ERRNO_IS_NOT_SUPPORTED ( errno ) ) {
log_notice ( " Skipping CLONE_NEWPID reaper check, lacking privileges/support " ) ;
_exit ( EXIT_SUCCESS ) ;
}
}
2024-09-19 12:04:34 +02:00
r = safe_fork ( " (newpid1) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_REOPEN_LOG | FORK_WAIT , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2023-06-22 11:52:06 +02:00
if ( r = = 0 ) {
/* grandchild, which is PID1 in a pidns */
2024-09-19 11:39:09 +02:00
ASSERT_OK_EQ ( getpid_cached ( ) , 1 ) ;
ASSERT_OK_POSITIVE ( is_reaper_process ( ) ) ;
2023-06-22 11:52:06 +02:00
_exit ( EXIT_SUCCESS ) ;
}
_exit ( EXIT_SUCCESS ) ;
}
2024-09-19 12:04:34 +02:00
r = safe_fork ( " (subreaper) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_REOPEN_LOG | FORK_WAIT , NULL ) ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( r ) ;
2023-06-22 11:52:06 +02:00
if ( r = = 0 ) {
/* child */
2024-09-19 11:39:09 +02:00
ASSERT_OK ( make_reaper_process ( true ) ) ;
2023-06-22 11:52:06 +02:00
2024-09-19 11:39:09 +02:00
ASSERT_OK_POSITIVE ( is_reaper_process ( ) ) ;
2023-06-22 11:52:06 +02:00
_exit ( EXIT_SUCCESS ) ;
}
}
2023-11-23 18:09:30 +01:00
TEST ( pid_get_start_time ) {
_cleanup_ ( pidref_done ) PidRef pidref = PIDREF_NULL ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pidref_set_self ( & pidref ) ) ;
2023-11-23 18:09:30 +01:00
2024-05-22 00:23:50 +08:00
usec_t start_time ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pidref_get_start_time ( & pidref , & start_time ) ) ;
2024-05-22 00:23:50 +08:00
log_info ( " our starttime: " USEC_FMT , start_time ) ;
2023-11-23 18:09:30 +01:00
_cleanup_ ( pidref_done_sigkill_wait ) PidRef child = PIDREF_NULL ;
2024-09-19 12:04:34 +02:00
ASSERT_OK ( pidref_safe_fork ( " (stub) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_REOPEN_LOG , & child ) ) ;
2023-11-23 18:09:30 +01:00
2024-05-22 00:23:50 +08:00
usec_t start_time2 ;
2024-09-19 11:39:09 +02:00
ASSERT_OK ( pidref_get_start_time ( & child , & start_time2 ) ) ;
2023-11-23 18:09:30 +01:00
2024-05-22 00:23:50 +08:00
log_info ( " child starttime: " USEC_FMT , start_time2 ) ;
2023-11-23 18:09:30 +01:00
2024-09-19 11:39:09 +02:00
ASSERT_GE ( start_time2 , start_time ) ;
2023-11-23 18:09:30 +01:00
}
tests: rework test macros to not take code as parameters
C macros are nasty. We use them, but we try to be conservative with
them. In particular passing literal, complex code blocks as argument is
icky, because of "," handling of C, and also because it's quite a
challange for most code highlighters and similar. Hence, let's avoid
that. Using macros for genreating functions is OK but if so, the
parameters should be simple words, not full code blocks.
hence, rework DEFINE_CUSTOM_TEST_MAIN() to take a function name instead
of code block as argument.
As side-effect this also fixes a bunch of cases where we might end up
returning a negative value from main().
Some uses of DEFINE_CUSTOM_TEST_MAIN() inserted local variables into the
main() functions, these are replaced by static variables, and their
destructors by the static destructor logic.
This doesn't fix any bugs or so, it's just supposed to make the code
easier to work with and improve it easthetically.
Or in other words: let's use macros where it really makes sense, but
let's not go overboard with it.
(And yes, FOREACH_DIRENT() is another one of those macros that take
code, and I dislike that too and regret I ever added that.)
2022-02-01 12:06:59 +01:00
static int intro ( void ) {
log_show_color ( true ) ;
return EXIT_SUCCESS ;
}
2022-02-02 11:06:41 +09:00
DEFINE_TEST_MAIN_WITH_INTRO ( LOG_INFO , intro ) ;