1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved. 4 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> 5 */ 6 7/* 8 * Description: 9 * Set CPU time limit for a process and check its behavior 10 * after reaching CPU time limit. 11 * 1) Process got SIGXCPU after reaching soft limit of CPU time. 12 * 2) Process got SIGKILL after reaching hard limit of CPU time. 13 * 14 * Note: 15 * This is also a regression test for the following kernel bug: 16 * 'c3bca5d450b62 ("posix-cpu-timers: Ensure set_process_cpu_timer is always evaluated")' 17 */ 18 19#define _GNU_SOURCE 20#include <errno.h> 21#include <sys/types.h> 22#include <unistd.h> 23#include <sys/time.h> 24#include <sys/resource.h> 25#include <sys/wait.h> 26#include <stdlib.h> 27#include <sys/mman.h> 28 29#include "tst_test.h" 30 31static int *end; 32 33static void sighandler(int sig) 34{ 35 *end = sig; 36} 37 38static void setup(void) 39{ 40 SAFE_SIGNAL(SIGXCPU, sighandler); 41 42 end = SAFE_MMAP(NULL, sizeof(int), PROT_READ | PROT_WRITE, 43 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 44} 45 46static void cleanup(void) 47{ 48 if (end) 49 SAFE_MUNMAP(end, sizeof(int)); 50} 51 52static void verify_setrlimit(void) 53{ 54 int status; 55 pid_t pid; 56 57 *end = 0; 58 59 pid = SAFE_FORK(); 60 if (!pid) { 61 struct rlimit rlim = { 62 .rlim_cur = 1, 63 .rlim_max = 2, 64 }; 65 66 TEST(setrlimit(RLIMIT_CPU, &rlim)); 67 if (TST_RET == -1) { 68 tst_res(TFAIL | TTERRNO, 69 "setrlimit(RLIMIT_CPU) failed"); 70 exit(1); 71 } 72 73 alarm(20); 74 75 while (1); 76 } 77 78 SAFE_WAITPID(pid, &status, 0); 79 80 if (WIFEXITED(status) && WEXITSTATUS(status) == 1) 81 return; 82 83 if (WIFSIGNALED(status)) { 84 if (WTERMSIG(status) == SIGKILL && *end == SIGXCPU) { 85 tst_res(TPASS, 86 "Got SIGXCPU then SIGKILL after reaching both limit"); 87 return; 88 } 89 90 if (WTERMSIG(status) == SIGKILL && !*end) { 91 tst_res(TFAIL, 92 "Got only SIGKILL after reaching both limit"); 93 return; 94 } 95 96 if (WTERMSIG(status) == SIGALRM && *end == SIGXCPU) { 97 tst_res(TFAIL, 98 "Got only SIGXCPU after reaching both limit"); 99 return; 100 } 101 102 if (WTERMSIG(status) == SIGALRM && !*end) { 103 tst_res(TFAIL, 104 "Got no signal after reaching both limit"); 105 return; 106 } 107 } 108 109 tst_res(TFAIL, "Child %s", tst_strstatus(status)); 110} 111 112static struct tst_test test = { 113 .test_all = verify_setrlimit, 114 .setup = setup, 115 .cleanup = cleanup, 116 .forks_child = 1, 117 .tags = (const struct tst_tag[]) { 118 {"linux-git", "c3bca5d450b62"}, 119 {} 120 } 121}; 122