Skip to content

Commit 27c7027

Browse files
committed
syscalls: refactor vfork02 using new API
Replace the deprecated sigrelse/sighold usage and replace them with sigprocmask/sigaction. Reviewed-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
1 parent bd8f13b commit 27c7027

File tree

1 file changed

+48
-200
lines changed

1 file changed

+48
-200
lines changed
Lines changed: 48 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -1,229 +1,77 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
12
/*
2-
*
3-
* Copyright (c) International Business Machines Corp., 2001
4-
*
5-
* This program is free software; you can redistribute it and/or modify
6-
* it under the terms of the GNU General Public License as published by
7-
* the Free Software Foundation; either version 2 of the License, or
8-
* (at your option) any later version.
9-
*
10-
* This program is distributed in the hope that it will be useful,
11-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13-
* the GNU General Public License for more details.
14-
*
15-
* You should have received a copy of the GNU General Public License
16-
* along with this program; if not, write to the Free Software
17-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3+
* Copyright (c) International Business Machines Corp., 2001
4+
* Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
185
*/
196

20-
/*
21-
* Test Name: vfork02
22-
*
23-
* Test Description:
7+
/*\
248
* Fork a process using vfork() and verify that, the pending signals in
259
* the parent are not pending in the child process.
26-
* $
27-
* Expected Result:
28-
* The signal which is pending in the parent should not be pending in the
29-
* child process.
30-
*
31-
* Algorithm:
32-
* Setup:
33-
* Setup signal handling.
34-
* Pause for SIGUSR1 if option specified.
35-
*
36-
* Test:
37-
* Loop if the proper options are given.
38-
* Execute system call
39-
* Check return code, if system call failed (return=-1)
40-
* Log the errno and Issue a FAIL message.
41-
* Otherwise,
42-
* Verify the Functionality of system call
43-
* if successful,
44-
* Issue Functionality-Pass message.
45-
* Otherwise,
46-
* Issue Functionality-Fail message.
47-
* Cleanup:
48-
* Print errno log and/or timing stats if options given
49-
*
50-
* Usage: <for command-line>
51-
* vfork02 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
52-
* where, -c n : Run n copies concurrently.
53-
* -e : Turn on errno logging.
54-
* -f : Turn off functionality Testing.
55-
* -i n : Execute test n times.
56-
* -I x : Execute test for x seconds.
57-
* -P x : Pause for x seconds between iterations.
58-
* -t : Turn on syscall timing.
59-
*
60-
* History
61-
* 07/2001 John George
62-
* -Ported
63-
*
64-
* Restrictions:
65-
* None.
66-
*
6710
*/
68-
#define _GNU_SOURCE 1
6911

70-
#include <stdio.h>
71-
#include <sys/types.h>
72-
#include <errno.h>
73-
#include <unistd.h>
74-
#include <fcntl.h>
75-
#include <string.h>
76-
#include <signal.h>
77-
#include <sys/stat.h>
78-
#include <sys/wait.h>
12+
#include "tst_test.h"
7913

80-
#include "test.h"
81-
#include "tso_safe_macros.h"
14+
static sigset_t mask;
8215

83-
char *TCID = "vfork02";
84-
int TST_TOTAL = 1;
16+
static void run(void)
17+
{
18+
if (!vfork()) {
19+
sigset_t signal;
8520

86-
void setup(); /* Main setup function of test */
87-
void cleanup(); /* cleanup function for the test */
88-
void sig_handler(); /* signal catching function */
21+
tst_res(TINFO, "child: verify if SIGUSR1 signal is not on hold");
8922

90-
int main(int ac, char **av)
91-
{
92-
int lc;
93-
pid_t cpid; /* process id of the child process */
94-
int exit_status; /* exit status of child process */
95-
sigset_t PendSig; /* variable to hold pending signal */
96-
97-
tst_parse_opts(ac, av, NULL, NULL);
98-
99-
setup();
100-
101-
for (lc = 0; TEST_LOOPING(lc); lc++) {
102-
103-
tst_count = 0;
104-
105-
/*
106-
* Call vfork(2) to create a child process without
107-
* fully copying the address space of parent.
108-
*/
109-
TEST(vfork());
110-
111-
if ((cpid = TEST_RETURN) == -1) {
112-
tst_resm(TFAIL, "vfork() Failed, errno=%d : %s",
113-
TEST_ERRNO, strerror(TEST_ERRNO));
114-
} else if (cpid == 0) { /* Child process */
115-
/*
116-
* Check whether the pending signal SIGUSR1
117-
* in the parent is also pending in the child
118-
* process by storing it in a variable.
119-
*/
120-
if (sigpending(&PendSig) == -1) {
121-
tst_resm(TFAIL, "sigpending function "
122-
"failed in child");
123-
_exit(1);
124-
}
125-
126-
/* Check if SIGUSR1 is pending in child */
127-
if (sigismember(&PendSig, SIGUSR1) != 0) {
128-
tst_resm(TFAIL, "SIGUSR1 also pending "
129-
"in child process");
130-
_exit(1);
131-
}
132-
133-
/*
134-
* Exit with normal exit code if everything
135-
* fine
136-
*/
137-
_exit(0);
138-
} else { /* parent process */
139-
/*
140-
* Let the parent process wait till child completes
141-
* its execution.
142-
*/
143-
wait(&exit_status);
144-
145-
/* Check for the exit status of child process */
146-
if (WEXITSTATUS(exit_status) == 0) {
147-
tst_resm(TPASS, "Call to vfork() "
148-
"successful");
149-
} else if (WEXITSTATUS(exit_status) == 1) {
150-
tst_resm(TFAIL,
151-
"Child process exited abnormally");
152-
}
153-
}
154-
tst_count++; /* incr. TEST_LOOP counter */
155-
}
23+
if (sigpending(&signal) == -1)
24+
tst_brk(TBROK | TERRNO, "sigpending() error");
15625

157-
cleanup();
158-
tst_exit();
26+
TST_EXP_EQ_LI(sigismember(&signal, SIGUSR1), 0);
15927

28+
_exit(0);
29+
}
16030
}
16131

162-
/*
163-
* void
164-
* setup() - performs all ONE TIME setup for this test.
165-
* This function installs signal handler for SIGUSR1, puts signal SIGUSR1
166-
* on hold and then sends the signal SIGUSR1 to itself so that it is in
167-
* pending state.
168-
*/
169-
void setup(void)
32+
static void sig_handler(LTP_ATTRIBUTE_UNUSED int signo)
17033
{
171-
sigset_t PendSig; /* variable to hold pending signal */
34+
}
17235

173-
tst_sig(FORK, DEF_HANDLER, cleanup);
36+
static void setup(void)
37+
{
38+
struct sigaction action;
39+
sigset_t signal;
17440

175-
TEST_PAUSE;
41+
tst_res(TINFO, "parent: hold SIGUSR1 signal");
17642

177-
/* Install the signal handler */
178-
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
179-
tst_brkm(TBROK, cleanup, "Fails to catch the signal SIGUSR1");
180-
}
43+
memset(&action, 0, sizeof(action));
44+
action.sa_handler = sig_handler;
45+
SAFE_SIGACTION(SIGUSR1, &action, NULL);
18146

182-
/* Hold the signal SIGUSR1 */
183-
if (sighold(SIGUSR1) == -1) {
184-
tst_brkm(TBROK, cleanup,
185-
"sighold failed to hold the signal SIGUSR1");
186-
}
47+
SAFE_SIGEMPTYSET(&mask);
48+
SAFE_SIGADDSET(&mask, SIGUSR1);
49+
SAFE_SIGPROCMASK(SIG_BLOCK, &mask, NULL);
18750

188-
/* Send the signal SIGUSR1 to itself so that SIGUSR1 is pending */
189-
SAFE_KILL(cleanup, getpid(), SIGUSR1);
51+
SAFE_KILL(getpid(), SIGUSR1);
19052

191-
/* If SIGUSR1 is not pending in the parent, fail */
192-
if (sigpending(&PendSig) == -1) {
193-
tst_brkm(TBROK, cleanup,
194-
"sigpending function failed in parent");
195-
}
53+
if (sigpending(&signal) == -1)
54+
tst_brk(TBROK | TERRNO, "sigpending() error");
55+
56+
TEST(sigismember(&signal, SIGUSR1));
57+
if (TST_RET != 1) {
58+
if (TST_RET == -1)
59+
tst_brk(TBROK | TERRNO, "sigismember() error");
19660

197-
/* Check if SIGUSR1 is pending in parent */
198-
if (sigismember(&PendSig, SIGUSR1) != 1) {
199-
tst_brkm(TBROK, cleanup,
200-
"SIGUSR1 signal is not pending in parent");
61+
tst_brk(TBROK, "SIGUSR1 is not on hold");
20162
}
20263
}
20364

204-
/*
205-
* void
206-
* sig_handler() - signal catching function for 'SIGUSR1' signal.
207-
* $
208-
* This is a null function and used only to catch the above signal
209-
* generated in parent process.
210-
*/
211-
void sig_handler(void)
65+
static void cleanup(void)
21266
{
67+
SAFE_SIGEMPTYSET(&mask);
68+
SAFE_SIGADDSET(&mask, SIGUSR1);
69+
SAFE_SIGPROCMASK(SIG_UNBLOCK, &mask, NULL);
21370
}
21471

215-
/*
216-
* void
217-
* cleanup() - performs all ONE TIME cleanup for this test at
218-
* completion or premature exit.
219-
* Release the signal 'SIGUSR1' if still in pending state.
220-
*/
221-
void cleanup(void)
222-
{
223-
224-
/* Release the signal 'SIGUSR1' if in pending state */
225-
if (sigrelse(SIGUSR1) == -1) {
226-
tst_brkm(TBROK, NULL, "Failed to release 'SIGUSR1' in cleanup");
227-
}
228-
229-
}
72+
static struct tst_test test = {
73+
.test_all = run,
74+
.setup = setup,
75+
.cleanup = cleanup,
76+
.forks_child = 1,
77+
};

0 commit comments

Comments
 (0)