[LTP] [PATCH] Convert ptrace01.c to new library

Tim.Bird@sony.com Tim.Bird@sony.com
Tue Oct 1 22:14:13 CEST 2019


> -----Original Message-----
> From: Jorik Cronenberg on Monday, September 30, 2019 9:01 PM
> To: ltp@lists.linux.it
> Subject: [LTP] [PATCH] Convert ptrace01.c to new library
> 
> Hi,
> 
> This is just a port of ptrace01.c. I wanted to make sure what I'm doing is right
> before porting the rest. I tried to make as little changes as possible so the
> test should be pretty much the same.
> ---
>  testcases/kernel/syscalls/ptrace/ptrace01.c | 296 +++++++---------------------
>  1 file changed, 72 insertions(+), 224 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/ptrace/ptrace01.c
> b/testcases/kernel/syscalls/ptrace/ptrace01.c
> index 5a7ed5ffd..ab9ef35ee 100644
> --- a/testcases/kernel/syscalls/ptrace/ptrace01.c
> +++ b/testcases/kernel/syscalls/ptrace/ptrace01.c
> @@ -1,36 +1,13 @@
> -/*
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
>   * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
>   *
> - * This program is free software; you can redistribute it and/or modify it
> - * under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> + * Author:	Saji Kumar.V.R <saji.kumar@wipro.com>
>   *
> - * This program is distributed in the hope that it would be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> + * Ported to new library:
> + * 10/2019	Jorik Cronenberg <jcronenberg@suse.de>
>   *
> - * You should have received a copy of the GNU General Public License along
> - * with this program; if not, write the Free Software Foundation, Inc.,
> - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> - *
> - */
> -
> /**********************************************************
> - *
> - *    TEST IDENTIFIER	: ptrace01
> - *
> - *    EXECUTED BY	: anyone
> - *
> - *    TEST TITLE	: functionality test for ptrace(2)
> - *
> - *    TEST CASE TOTAL	: 2
> - *
> - *    AUTHOR		: Saji Kumar.V.R <saji.kumar@wipro.com>
> - *
> - *    SIGNALS
> - * 	Uses SIGUSR1 to pause before test if option set.
> - * 	(See the parse_opts(3) man page).
> - *
> - *    DESCRIPTION
> + * DESCRIPTION
>   *	This test case tests the functionality of ptrace() for
>   *	PTRACE_TRACEME & PTRACE_KILL requests.
>   *	Here, we fork a child & the child does ptrace(PTRACE_TRACEME, ...).
> @@ -44,243 +21,114 @@
>   * 		In both cases, child should stop & notify parent on reception
>   * 		of SIGUSR2
>   *
> - * 	Setup:
> - * 	  Setup signal handling.
> - *	  Pause for SIGUSR1 if option specified.
> - *
> - * 	Test:
> - *	 Loop if the proper options are given.
> - *	 setup signal handler for SIGUSR2 signal
> - *	 fork a child
> - *
> - *	 CHILD:
> - *		setup signal handler for SIGUSR2 signal
> - *		call ptrace() with PTRACE_TRACEME request
> - *		send SIGUSR2 signal to self
> - *	 PARENT:
> - *		wait() for child.
> - *		if parent is notified when child gets a signal through wait(),
> - *		then
> - *			do  ptrace(PTRACE_KILL, ..) on child
> - * 			wait() for child to finish,
> - * 			if child exited abnormaly,
> - *				TEST passed
> - * 			else
> - * 				TEST failed
> - *		else
> - *			TEST failed
> - *
> - * 	Cleanup:
> - * 	  Print errno log and/or timing stats if options given
> - *
> - * USAGE:  <for command-line>
> - *  ptrace01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
> - *			where,  -c n : Run n copies concurrently.
> - *				-e   : Turn on errno logging.
> - *				-h   : Show help screen
> - *				-f   : Turn off functional testing
> - *				-i n : Execute test n times.
> - *				-I x : Execute test for x seconds.
> - *				-p   : Pause for SIGUSR1 before starting
> - *				-P x : Pause for x seconds between iterations.
> - *				-t   : Turn on syscall timing.
> - *
> -
> **********************************************************
> ******/
> + */

It looks like the old comment had some nicely structured meta-data.  I'm not
familiar with the process for converting to the new library.  Is it intentional to
eliminate this meta-data?  (This is more of a question for the LTP leaders
than for Jorik).

I know that Cyril is working on a new meta-data system.  If this meta-data is eliminated
now, does it make adding it back into the new system harder?

Personally, I find it useful to see the pseudo-code outline when I'm debugging a
test.  So I hate to see those be eliminated.  But maybe those are hard to trust
as they tend to not be maintained along with the code?
 -- Tim


> 
> +#include <stdlib.h>
>  #include <errno.h>
>  #include <signal.h>
>  #include <sys/wait.h>
> -
>  #include <config.h>
>  #include "ptrace.h"
> +#include "tst_test.h"
> 
> -#include "test.h"
> -
> -static void do_child(void);
> -static void setup(void);
> -static void cleanup(void);
> -static void child_handler();
> -static void parent_handler();
> +static int got_signal;
> 
> -static int got_signal = 0;
> -
> -char *TCID = "ptrace01";
> -static int i;			/* loop test case counter, shared with
> do_child */
> -
> -int TST_TOTAL = 2;
> -
> -int main(int ac, char **av)
> +void child_handler(void)
>  {
> -
> -	int lc;
> -	pid_t child_pid;
> -	int status;
> -	struct sigaction parent_act;
> -
> -	tst_parse_opts(ac, av, NULL, NULL);
> -#ifdef UCLINUX
> -	maybe_run_child(&do_child, "d", &i);
> -#endif
> -
> -	setup();
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> -
> -		tst_count = 0;
> -
> -		for (i = 0; i < TST_TOTAL; ++i) {
> -			got_signal = 0;
> -
> -			/* Setup signal handler for parent */
> -			if (i == 1) {
> -				parent_act.sa_handler = parent_handler;
> -				parent_act.sa_flags = SA_RESTART;
> -				sigemptyset(&parent_act.sa_mask);
> -
> -				if ((sigaction(SIGUSR2, &parent_act, NULL))
> -				    == -1) {
> -					tst_resm(TWARN, "sigaction() failed"
> -						 " in parent");
> -					continue;
> -				}
> -			}
> -
> -			switch (child_pid = FORK_OR_VFORK()) {
> -
> -			case -1:
> -				/* fork() failed */
> -				tst_resm(TFAIL, "fork() failed");
> -				continue;
> -
> -			case 0:
> -				/* Child */
> -#ifdef UCLINUX
> -				if (self_exec(av[0], "d", i) < 0) {
> -					tst_resm(TFAIL, "self_exec failed");
> -					continue;
> -				}
> -#else
> -				do_child();
> -#endif
> -
> -			default:
> -				/* Parent */
> -				if ((waitpid(child_pid, &status, 0)) < 0) {
> -					tst_resm(TFAIL, "waitpid() failed");
> -					continue;
> -				}
> -
> -				/*
> -				 * Check the exit status of child. If (it exits
> -				 * normally with exit value 1) OR (child came
> -				 * through signal handler), Test Failed
> -				 */
> -
> -				if (((WIFEXITED(status)) &&
> -				     (WEXITSTATUS(status))) ||
> -				    (got_signal == 1)) {
> -					tst_resm(TFAIL, "Test Failed");
> -					continue;
> -				} else {
> -					/* Kill child */
> -					if ((ptrace(PTRACE_KILL, child_pid,
> -						    0, 0)) == -1) {
> -						tst_resm(TFAIL, "Test Failed:"
> -							 " Parent was not able
> to kill"
> -							 " child");
> -						continue;
> -					}
> -				}
> -
> -				if ((waitpid(child_pid, &status, 0)) < 0) {
> -					tst_resm(TFAIL, "waitpid() failed");
> -					continue;
> -				}
> -
> -				if (WIFEXITED(status)) {
> -					/* Child exits normally */
> -					tst_resm(TFAIL, "Test failed");
> -				} else {
> -					tst_resm(TPASS, "Test Passed");
> -				}
> -
> -			}
> -		}
> +	if ((kill(getppid(), SIGUSR2)) == -1) {
> +		tst_res(TWARN, "kill() failed in child_handler()");
> +		exit(1);
>  	}
> +}
> 
> -	/* cleanup and exit */
> -	cleanup();
> -	tst_exit();
> -
> +void parent_handler(void)
> +{
> +	got_signal = 1;
>  }
> 
> -/* do_child() */
> -void do_child(void)
> +void do_child(unsigned int i)
>  {
>  	struct sigaction child_act;
> 
> -	/* Setup signal handler for child */
> -	if (i == 0) {
> +	if (i == 0)
>  		child_act.sa_handler = SIG_IGN;
> -	} else {
> +	else
>  		child_act.sa_handler = child_handler;
> -	}
> +
>  	child_act.sa_flags = SA_RESTART;
>  	sigemptyset(&child_act.sa_mask);
> 
>  	if ((sigaction(SIGUSR2, &child_act, NULL)) == -1) {
> -		tst_resm(TWARN, "sigaction() failed in child");
> +		tst_res(TWARN, "sigaction() failed in child");
>  		exit(1);
>  	}
> 
>  	if ((ptrace(PTRACE_TRACEME, 0, 0, 0)) == -1) {
> -		tst_resm(TWARN, "ptrace() failed in child");
> +		tst_res(TWARN, "ptrace() failed in child");
>  		exit(1);
>  	}
> -	/* ensure that child bypasses signal handler */
>  	if ((kill(getpid(), SIGUSR2)) == -1) {
> -		tst_resm(TWARN, "kill() failed in child");
> +		tst_res(TWARN, "kill() failed in child");
>  		exit(1);
>  	}
>  	exit(1);
>  }
> 
> -/* setup() - performs all ONE TIME setup for this test */
> -void setup(void)
> +static void run(unsigned int i)
>  {
> 
> -	tst_sig(FORK, DEF_HANDLER, cleanup);
> +	pid_t child_pid;
> +	int status;
> +	struct sigaction parent_act;
> 
> -	TEST_PAUSE;
> +#ifdef UCLINUX
> +	maybe_run_child(&do_child, "d", &i);
> +#endif
> 
> -}
> +	got_signal = 0;
> 
> -/*
> - *cleanup() -  performs all ONE TIME cleanup for this test at
> - *		completion or premature exit.
> - */
> -void cleanup(void)
> -{
> +	if (i == 1) {
> +		parent_act.sa_handler = parent_handler;
> +		parent_act.sa_flags = SA_RESTART;
> +		sigemptyset(&parent_act.sa_mask);
> 
> -}
> +		if ((sigaction(SIGUSR2, &parent_act, NULL))
> +		    == -1) {
> +			tst_res(TWARN, "sigaction() failed in parent");
> +		}
> +	}
> 
> -/*
> - * child_handler() - Signal handler for child
> - */
> -void child_handler(void)
> -{
> +	child_pid = SAFE_FORK();
> 
> -	if ((kill(getppid(), SIGUSR2)) == -1) {
> -		tst_resm(TWARN, "kill() failed in child_handler()");
> -		exit(1);
> -	}
> -}
> +	if (child_pid != 0) {
> 
> -/*
> - * parent_handler() - Signal handler for parent
> - */
> -void parent_handler(void)
> -{
> +		SAFE_WAITPID(child_pid, &status, 0);
> 
> -	got_signal = 1;
> +		if (((WIFEXITED(status)) &&
> +		     (WEXITSTATUS(status))) ||
> +		    (got_signal == 1)) {
> +			tst_res(TFAIL, "Test Failed");
> +		} else {
> +			if ((ptrace(PTRACE_KILL, child_pid,
> +				    0, 0)) == -1) {
> +				tst_res(TFAIL,
> +						"Test Failed: Parent was not
> able to kill child");
> +			}
> +		}
> +
> +		SAFE_WAITPID(child_pid, &status, 0);
> +
> +		if (WIFEXITED(status))
> +			tst_res(TFAIL, "Test failed");
> +		else
> +			tst_res(TPASS, "Test Passed");
> +
> +	} else
> +		do_child(i);
>  }
> +
> +static struct tst_test test = {
> +	.test = run,
> +	.tcnt = 2,
> +	.forks_child = 1,
> +};
> --
> 2.16.4
> 
> 
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp


More information about the ltp mailing list