[LTP] [PATCH] syscalls/kill12: Convert to new API

Andrea Cervesato andrea.cervesato@suse.com
Tue Jun 24 10:45:24 CEST 2025


Hi!

On 6/17/25 5:56 PM, Ricardo B. Marlière via ltp wrote:
> From: Ricardo B. Marlière <rbm@suse.com>
>
> Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
> ---
>   testcases/kernel/syscalls/kill/kill12.c | 277 +++++++++-----------------------
>   1 file changed, 72 insertions(+), 205 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/kill/kill12.c b/testcases/kernel/syscalls/kill/kill12.c
> index f864bdcb654c563cd4808bec7a4979fb160825c4..d843fe5fba62f63dc903759192fbfb7cd02bc7b6 100644
> --- a/testcases/kernel/syscalls/kill/kill12.c
> +++ b/testcases/kernel/syscalls/kill/kill12.c
> @@ -1,236 +1,103 @@
> -/* IBM Corporation */
> -/* 01/02/2003	Port to LTP avenkat@us.ibm.com */
> -/* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
> -
> +// SPDX-License-Identifier: GPL-2.0-or-later
>   /*
> - *
> - *   Copyright (c) International Business Machines  Corp., 2002
> - *
> - *   This program 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.
> - *
> - *   This program 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 this program;  if not, write to the Free Software
> - *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Copyright (c) International Business Machines  Corp., 2002
> + *	01/02/2003	Port to LTP	avenkat@us.ibm.com
> + *	06/30/2001	Port to Linux	nsharoff@us.ibm.com
> + * Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
>    */
>   
> -			   /*kill2.c */
> -/*======================================================================
> ->KEYS:  < kill(), wait(), signal()
> ->WHAT:  < Check that when a child is killed by its parent, it returns the
> -	< correct values to the waiting parent--the child sets signal to
> -	< ignore the kill
> ->HOW:   < For each signal: Send that signal to a child that has elected
> -	< to catch the signal, check that the correct status was returned
> -	< to the waiting parent.
> -	< NOTE: Signal 9 (kill) is not catchable, and must be dealt with
> -	< separately.
> ->BUGS:  < None known
> -======================================================================*/
> -#ifndef _GNU_SOURCE
> -#define _GNU_SOURCE 1
> -#endif
> -
> -#include <stdio.h>
> -#include <sys/types.h>
> -#include <signal.h>
> -#include <stdlib.h>
> -#include <unistd.h>
> -#include <sys/wait.h>
> -#include <errno.h>
> +/*\
> + * Check that when a child is killed by its parent, it returns the
> + * correct values to the waiting parent - the child sets signal to
> + * ignore the kill
> + */
>   
> -#include "test.h"
> -#define ITER    3
> -#define FAILED 0
> -#define PASSED 1
> +#define _GNU_SOURCE
> +#include <sys/wait.h>
Both are not needed with the suggestions below.
>   
> -char *TCID = "kill12";
> +#include "tst_test.h"
>   
> -int local_flag = PASSED;
> -int block_number;
> -FILE *temp;
> -int TST_TOTAL = 1;
>   static int sig;
> +static int chflag;
>   
> -int anyfail();
> -int blenter();
> -int instress();
> -void setup();
> -void terror();
> -void fail_exit();
> -void ok_exit();
> -int forkfail();
> -void do_child();
> +static void do_child(void);
>   
> -int chflag;
> -
> -int main(int argc, char **argv)
> +static void run(void)
>   {
> -	int pid, npid;
> -	int nsig, exno, nexno, status;
> -	int ret_val = 0;
> -	int core;
> -	void chsig();
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	setup();
> -	blenter();
> -
> -	exno = 1;
> -
> -	if (sigset(SIGCHLD, chsig) == SIG_ERR) {
> -		fprintf(temp, "\tsigset failed, errno = %d\n", errno);
> -		fail_exit();
> -	}
> +	int pid;
> +	int nsig, nexno, status;
>   
>   	for (sig = 1; sig < 14; sig++) {
Why not just "int sig" ?
> -		fflush(temp);
> -		chflag = 0;
> +		/* SIGKILL and SIGSTOP can't be catched */
> +		if (sig == SIGKILL || sig == SIGSTOP)
> +			continue;
>   
> -		pid = tst_fork();
> -		if (pid < 0) {
> -			forkfail();
> -		}
> +		chflag = 0;
>   
> -		if (pid == 0) {
> +		pid = SAFE_FORK();
> +		if (!pid)
>   			do_child();
> -		} else {
> -			//fprintf(temp, "Testing signal %d\n", sig);
> -
> -			while (!chflag)	/* wait for child */
> -				sleep(1);
> -
> -			kill(pid, sig);	/* child should ignroe this sig */
> -			kill(pid, SIGCHLD);	/* child should exit */
> -
> -#ifdef BCS
> -			while ((npid = wait(&status)) != pid
> -			       || (npid == -1 && errno == EINTR)) ;
> -			if (npid != pid) {
> -				fprintf(temp,
> -					"wait error: wait returned wrong pid\n");
> -				ret_val = 1;
> -			}
> -#else
> -			while ((npid = waitpid(pid, &status, 0)) != -1
> -			       || errno == EINTR) ;
> -#endif
> -
> -			/*
> -			   nsig = status & 0177;
> -			   core = status & 0200;
> -			   nexno = (status & 0xff00) >> 8;
> -			 */
> -			/*****  LTP Port        *****/
> -			nsig = WTERMSIG(status);
> -#ifdef WCOREDUMP
> -			core = WCOREDUMP(status);
> -#endif
> -			nexno = WIFEXITED(status);
> -			/*****  **      **      *****/
> -
> -			/* nsig is the signal number returned by wait
> -			   it should be 0, except when sig = 9          */
> -
> -			if ((sig == 9) && (nsig != sig)) {
> -				fprintf(temp, "wait error: unexpected signal"
> -					" returned when the signal sent was 9"
> -					" The status of the process is %d \n",
> -					status);
> -				ret_val = 1;
> -			}
> -			if ((sig != 9) && (nsig != 0)) {
> -				fprintf(temp, "wait error: unexpected signal "
> -					"returned, the status of the process is "
> -					"%d  \n", status);
> -				ret_val = 1;
> -			}
> -
> -			/* nexno is the exit number returned by wait
> -			   it should be 1, except when sig = 9          */
> -
> -			if (sig == 9)
> -				if (nexno != 0) {
> -					fprintf(temp, "signal error: unexpected"
> -						" exit number returned when"
> -						" signal sent was 9, the status"
> -						" of the process is %d \n",
> -						status);
> -					ret_val = 1;
> -				} else;
> -			else if (nexno != 1) {
> -				fprintf(temp, "signal error: unexpected exit "
> -					"number returned,the status of the"
> -					" process is %d\n", status);
> -				ret_val = 1;
> -			}
> -		}
> +
> +		while (!chflag) /* wait for child */
> +			sleep(1);
No need to sync parent and child with a while loop. We have checkpoints:

         pid = SAFE_FORK();

         if (!pid) {
             TST_CHECKPOINT_WAKE_AND_WAIT(0);
             exit(1);
         }

         TST_CHECKPOINT_WAIT(0);

> +
> +		SAFE_KILL(pid, sig); /* child should ignore this sig */
> +		SAFE_KILL(pid, SIGCHLD); /* child should exit */
> +		SAFE_WAITPID(pid, &status, 0);
> +		nsig = WTERMSIG(status);
> +		nexno = WIFEXITED(status);
> +
> +		/* nsig is the signal number returned by wait, it should be 0 */
> +		if (nsig != 0)
> +			tst_res(TFAIL,
> +				"wait error: unexpected signal "
> +				"returned, the status of the process is %d",
> +				status);
> +
> +		/* nexno is the exit number returned by wait, it should be 1 */
> +		if (nexno != 1)
> +			tst_res(TFAIL,
> +				"signal error: unexpected exit "
> +				"number returned,the status of the"
> +				" process is %d\n",
> +				status);
These two statements can be shrinked to TST_EXP_EQ_LI(WTERMSIG(status), 
sig) , etc.
>   	}
> -	if (ret_val)
> -		local_flag = FAILED;
>   
> -	anyfail();
> -	tst_exit();
> +	tst_res(TPASS, "Test passed");
No need for this once we check the child status with TST_EXP_EQ_LI().
>   }
>   
> -void chsig(void)
> +static void chsig(LTP_ATTRIBUTE_UNUSED int signum,
> +		  LTP_ATTRIBUTE_UNUSED siginfo_t *si,
> +		  LTP_ATTRIBUTE_UNUSED void *uc)
>   {
>   	chflag++;
>   }
No need for this with checkpoints.
>   
> -int anyfail(void)
> +static void do_child(void)
>   {
> -	(local_flag == FAILED) ? tst_resm(TFAIL,
> -					  "Test failed") : tst_resm(TPASS,
> -								    "Test passed");
> -	tst_exit();
> -}
> +	struct sigaction sa = {
> +		.sa_handler = SIG_IGN,
> +		.sa_flags = 0,
> +	};
No need for this with checkpoints.
>   
> -void do_child(void)
> -{
> -	int exno = 1;
> -
> -	sigset(sig, SIG_IGN);	/* set to ignore signal */
> -	kill(getppid(), SIGCHLD);	/* tell parent we are ready */
> +	SAFE_SIGACTION(sig, &sa, NULL);
> +	SAFE_KILL(getppid(), SIGCHLD); /* tell parent we are ready */
>   	while (!chflag)
> -		sleep(1);	/* wait for parent */
> -
> -	exit(exno);
> -}
> -
> -void setup(void)
> -{
> -	temp = stderr;
> -}
> -
> -int blenter(void)
> -{
> -	//tst_resm(TINFO, "Enter block %d", block_number);
> -	local_flag = PASSED;
> -	return 0;
> +		sleep(1); /* wait for parent */
> +	exit(1);
>   }
>   
> -void terror(char *message)
> +static void setup(void)
>   {
> -	tst_resm(TBROK, "Reason: %s:%s", message, strerror(errno));
> +	struct sigaction sa = {
> +		.sa_sigaction = chsig,
> +		.sa_flags = 0,
> +	};
> +	SAFE_SIGACTION(SIGCHLD, &sa, NULL);
>   }
>   
> -void fail_exit(void)
> -{
> -	local_flag = FAILED;
> -	anyfail();
> -
> -}
> -
> -int forkfail(void)
> -{
> -	tst_brkm(TBROK, NULL, "FORK FAILED - terminating test.");
> -}
> +static struct tst_test test = {
> +	.test_all = run,
> +	.setup = setup,
> +	.forks_child = 1,
> +};
>
> ---
> base-commit: df591113afeb31107bc45bd5ba28a99b556d1028
> change-id: 20250617-conversions-kill-d79ed23a8c6b
>
> Best regards,
- Andrea


More information about the ltp mailing list