[LTP] [PATCH v3] Rewrite msgstress testing suite
Andrea Cervesato
andrea.cervesato@suse.de
Fri May 3 11:31:51 CEST 2024
From: Andrea Cervesato <andrea.cervesato@suse.com>
msgstress testing suite has been rewritten, taking in consideration
that old code was not working most of the times. The new algorithm
simply generates new SysV IPC messages, spawning a sender and a
receiver which will validate data.
With the new algorithm we also reduce the amount of children which
we spawn, since we only have 2: sender and receiver. This permits to
increase the number of messages to send and to do not be depedent from
system overload.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Remove KEY_VAL0 and use IPC_PRIVATE
Rename *failure with *stop
Wait for all children to stop before checking *stop
reader() now uses pos variable
*stop as "volatile int"
runtest/syscalls | 6 +-
runtest/syscalls-ipc | 6 +-
.../kernel/syscalls/ipc/msgstress/.gitignore | 3 -
.../kernel/syscalls/ipc/msgstress/Makefile | 5 -
.../syscalls/ipc/msgstress/msgstress01.c | 450 ++++++++----------
.../syscalls/ipc/msgstress/msgstress02.c | 408 ----------------
.../syscalls/ipc/msgstress/msgstress03.c | 299 ------------
.../syscalls/ipc/msgstress/msgstress04.c | 444 -----------------
8 files changed, 207 insertions(+), 1414 deletions(-)
delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress04.c
diff --git a/runtest/syscalls b/runtest/syscalls
index b9dd9fec6..fabb196be 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -864,12 +864,10 @@ msgctl03 msgctl03
msgctl04 msgctl04
msgctl05 msgctl05
msgctl06 msgctl06
-msgstress01 msgstress01
-msgstress02 msgstress02
-msgstress03 msgstress03
-msgstress04 msgstress04
msgctl12 msgctl12
+msgstress01 msgstress01
+
msgget01 msgget01
msgget02 msgget02
msgget03 msgget03
diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc
index 9860394de..8960c487c 100644
--- a/runtest/syscalls-ipc
+++ b/runtest/syscalls-ipc
@@ -4,12 +4,10 @@ msgctl03 msgctl03
msgctl04 msgctl04
msgctl05 msgctl05
msgctl06 msgctl06
-msgstress01 msgstress01
-msgstress02 msgstress02
-msgstress03 msgstress03
-msgstress04 msgstress04
msgctl12 msgctl12
+msgstress01 msgstress01
+
msgget01 msgget01
msgget02 msgget02
msgget03 msgget03
diff --git a/testcases/kernel/syscalls/ipc/msgstress/.gitignore b/testcases/kernel/syscalls/ipc/msgstress/.gitignore
index a8f675399..fe9780693 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/.gitignore
+++ b/testcases/kernel/syscalls/ipc/msgstress/.gitignore
@@ -1,4 +1 @@
/msgstress01
-/msgstress02
-/msgstress03
-/msgstress04
diff --git a/testcases/kernel/syscalls/ipc/msgstress/Makefile b/testcases/kernel/syscalls/ipc/msgstress/Makefile
index b821bda01..442eb87d5 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/Makefile
+++ b/testcases/kernel/syscalls/ipc/msgstress/Makefile
@@ -3,10 +3,5 @@
top_srcdir ?= ../../../../..
-LTPLIBS = ltpipc
-
include $(top_srcdir)/include/mk/testcases.mk
-
-LTPLDLIBS += -lltpipc
-
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
index 84e338437..5851938dd 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
+++ b/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
@@ -1,301 +1,257 @@
+// 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
- *
- * 06/30/2001 Port to Linux nsharoff@us.ibm.com
- * 11/06/2002 Port to LTP dbarrera@us.ibm.com
+ * Copyright (c) International Business Machines Corp., 2002
+ * 06/30/2001 Port to Linux nsharoff@us.ibm.com
+ * 11/11/2002 Port to LTP dbarrera@us.ibm.com
+ * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
/*
- * Get and manipulate a message queue.
+ * [Description]
+ *
+ * Stress test for SysV IPC. We send multiple messages at the same time,
+ * checking that we are not loosing any byte once we receive the messages
+ * from multiple children.
+ *
+ * The number of messages to send is determined by the free slots available
+ * in SysV IPC and the available number of children which can be spawned by
+ * the process. Each sender will spawn multiple messages at the same time and
+ * each receiver will read them one by one.
*/
-#define _XOPEN_SOURCE 500
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <values.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress01";
-int TST_TOTAL = 1;
-
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNREPS 100000
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int tid;
-static int MSGMNI, nprocs, nreps;
-static int procstat;
-static int mykid;
-
-void setup(void);
-void cleanup(void);
-
-static int dotest(key_t key, int child_process);
-static void sig_handler();
-
-static char *opt_nprocs;
-static char *opt_nreps;
-
-static option_t options[] = {
- {"n:", NULL, &opt_nprocs},
- {"l:", NULL, &opt_nreps},
- {NULL, NULL, NULL},
+#include "tst_safe_sysv_ipc.h"
+#include "tst_safe_stdio.h"
+#include "tst_test.h"
+
+#define SYSVIPC_TOTAL "/proc/sys/kernel/msgmni"
+#define SYSVIPC_USED "/proc/sysvipc/msg"
+#define MSGTYPE 10
+#define MAXNREPS 100000
+
+struct sysv_msg {
+ long type;
+ struct {
+ char len;
+ char pbytes[99];
+ } data;
+};
+
+struct sysv_data {
+ int id;
+ struct sysv_msg msg;
};
-static void usage(void)
+static struct sysv_data *ipc_data;
+static int ipc_data_len;
+
+static char *str_num_messages;
+static char *str_num_iterations;
+static int num_messages = 1000;
+static int num_iterations = MAXNREPS;
+static volatile int *stop;
+
+static int get_used_sysvipc(void)
{
- printf(" -n Number of processes\n");
- printf(" -l Number of iterations\n");
+ FILE *fp;
+ int used = -1;
+ char buf[BUFSIZ];
+
+ fp = SAFE_FOPEN(SYSVIPC_USED, "r");
+
+ while (fgets(buf, BUFSIZ, fp) != NULL)
+ used++;
+
+ SAFE_FCLOSE(fp);
+
+ if (used < 0)
+ tst_brk(TBROK, "Can't read %s to get used sysvipc resource", SYSVIPC_USED);
+
+ return used;
}
-int main(int argc, char **argv)
+static void reset_messages(void)
{
- int i, j, ok, pid;
- int count, status;
- struct sigaction act;
+ ipc_data_len = 0;
+ memset(ipc_data, 0, sizeof(struct sysv_data) * num_messages);
- tst_parse_opts(argc, argv, options, usage);
+ for (int i = 0; i < num_messages; i++)
+ ipc_data[i].id = -1;
+}
- setup();
+static int create_message(const int id)
+{
+ int pos = ipc_data_len;
+ struct sysv_data *buff = ipc_data + pos;
- nreps = MAXNREPS;
- nprocs = MSGMNI;
+ buff->id = id;
+ buff->msg.type = MSGTYPE;
+ buff->msg.data.len = (rand() % 99) + 1;
- if (opt_nreps) {
- nreps = atoi(opt_nreps);
- if (nreps > MAXNREPS) {
- tst_resm(TINFO,
- "Requested number of iterations too large, "
- "setting to Max. of %d", MAXNREPS);
- nreps = MAXNREPS;
- }
- }
+ for (int i = 0; i < buff->msg.data.len; i++)
+ buff->msg.data.pbytes[i] = rand() % 255;
- if (opt_nprocs) {
- nprocs = atoi(opt_nprocs);
- if (nprocs > MSGMNI) {
- tst_resm(TINFO,
- "Requested number of processes too large, "
- "setting to Max. of %d", MSGMNI);
- nprocs = MSGMNI;
- }
- }
+ ipc_data_len++;
- srand(getpid());
- tid = -1;
+ return pos;
+}
- /* Setup signal handling routine */
- memset(&act, 0, sizeof(act));
- act.sa_handler = sig_handler;
- sigemptyset(&act.sa_mask);
- sigaddset(&act.sa_mask, SIGTERM);
- if (sigaction(SIGTERM, &act, NULL) < 0) {
- tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
- }
- /* Set up array of unique keys for use in allocating message
- * queues
- */
- for (i = 0; i < nprocs; i++) {
- ok = 1;
- do {
- /* Get random key */
- keyarray[i] = (key_t) rand();
- /* Make sure key is unique and not private */
- if (keyarray[i] == IPC_PRIVATE) {
- ok = 0;
- continue;
- }
- for (j = 0; j < i; j++) {
- if (keyarray[j] == keyarray[i]) {
- ok = 0;
- break;
- }
- ok = 1;
- }
- } while (ok == 0);
- }
+static void writer(const int id, const int pos)
+{
+ struct sysv_data *buff = &ipc_data[pos];
+ int iter = num_iterations;
- /* Fork a number of processes, each of which will
- * create a message queue with one reader/writer
- * pair which will read and write a number (iterations)
- * of random length messages with specific values.
- */
+ while (--iter >= 0 && !(*stop))
+ SAFE_MSGSND(id, &buff->msg, 100, 0);
+}
+
+static void reader(const int id, const int pos)
+{
+ int size;
+ int iter = num_iterations;
+ struct sysv_msg msg_recv;
+ struct sysv_data *buff = &ipc_data[pos];
+
+ while (--iter >= 0 && !(*stop)) {
+ memset(&msg_recv, 0, sizeof(struct sysv_msg));
+
+ size = SAFE_MSGRCV(id, &msg_recv, 100, MSGTYPE, 0);
+
+ if (msg_recv.type != buff->msg.type) {
+ tst_res(TFAIL, "Received the wrong message type");
- for (i = 0; i < nprocs; i++) {
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- tst_brkm(TFAIL,
- NULL,
- "\tFork failed (may be OK if under stress)");
+ *stop = 1;
+ return;
}
- /* Child does this */
- if (pid == 0) {
- procstat = 1;
- exit(dotest(keyarray[i], i));
+
+ if (msg_recv.data.len != buff->msg.data.len) {
+ tst_res(TFAIL, "Received the wrong message data length");
+
+ *stop = 1;
+ return;
}
- pidarray[i] = pid;
- }
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != 0) {
- tst_brkm(TFAIL, NULL,
- "Child exit status = %d",
- status >> 8);
- }
- count++;
- } else {
- if (errno != EINTR) {
- break;
+ for (int i = 0; i < size; i++) {
+ if (msg_recv.data.pbytes[i] != buff->msg.data.pbytes[i]) {
+ tst_res(TFAIL, "Received wrong data at index %d: %x != %x", i,
+ msg_recv.data.pbytes[i],
+ buff->msg.data.pbytes[i]);
+
+ *stop = 1;
+ return;
}
-#ifdef DEBUG
- tst_resm(TINFO, "Signal detected during wait");
-#endif
}
- }
- /* Make sure proper number of children exited */
- if (count != nprocs) {
- tst_brkm(TFAIL,
- NULL,
- "Wrong number of children exited, Saw %d, Expected %d",
- count, nprocs);
- }
- tst_resm(TPASS, "Test ran successfully!");
+ tst_res(TDEBUG, "Received correct data");
+ tst_res(TDEBUG, "msg_recv.type = %ld", msg_recv.type);
+ tst_res(TDEBUG, "msg_recv.data.len = %d", msg_recv.data.len);
+ }
- cleanup();
- tst_exit();
+ buff->id = -1;
}
-static int dotest(key_t key, int child_process)
+static void run(void)
{
- int id, pid;
- int ret, status;
+ int id, pos;
- sighold(SIGTERM);
- TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
- if (TEST_RETURN < 0) {
- printf("msgget() error in child %d: %s\n",
- child_process, strerror(TEST_ERRNO));
+ reset_messages();
- return FAIL;
- }
- tid = id = TEST_RETURN;
- sigrelse(SIGTERM);
-
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("\tFork failed (may be OK if under stress)\n");
- TEST(msgctl(tid, IPC_RMID, 0));
- if (TEST_RETURN < 0) {
- printf("mscgtl() error in cleanup: %s\n",
- strerror(TEST_ERRNO));
+ for (int i = 0; i < num_messages; i++) {
+ id = SAFE_MSGGET(IPC_PRIVATE, IPC_CREAT | 0600);
+ pos = create_message(id);
+
+ if (!SAFE_FORK()) {
+ writer(id, pos);
+ return;
}
- return FAIL;
- }
- /* Child does this */
- if (pid == 0)
- exit(doreader(key, id, 1, child_process, nreps));
- /* Parent does this */
- mykid = pid;
- procstat = 2;
- ret = dowriter(key, id, 1, child_process, nreps);
- wait(&status);
-
- if (ret != PASS)
- exit(FAIL);
-
- if ((!WIFEXITED(status) || (WEXITSTATUS(status) != PASS)))
- exit(FAIL);
-
- TEST(msgctl(id, IPC_RMID, 0));
- if (TEST_RETURN < 0) {
- printf("msgctl() errno %d: %s\n",
- TEST_ERRNO, strerror(TEST_ERRNO));
-
- return FAIL;
+
+ if (!SAFE_FORK()) {
+ reader(id, pos);
+ return;
+ }
+
+ if (*stop)
+ break;
}
- return PASS;
-}
-static void sig_handler(void)
-{
+ tst_reap_children();
+
+ if (!(*stop))
+ tst_res(TPASS, "Test passed. All messages have been received");
}
-void setup(void)
+static void setup(void)
{
- int nr_msgqs;
+ int total_msg;
+ int avail_msg;
+ int free_msgs;
+ int free_pids;
- tst_tmpdir();
+ srand(time(0));
- tst_sig(FORK, DEF_HANDLER, cleanup);
+ SAFE_FILE_SCANF(SYSVIPC_TOTAL, "%i", &total_msg);
- TEST_PAUSE;
+ free_msgs = total_msg - get_used_sysvipc();
- nr_msgqs = get_max_msgqueues();
- if (nr_msgqs < 0)
- cleanup();
+ /* We remove 10% of free pids, just to be sure
+ * we won't saturate the sysyem with processes.
+ */
+ free_pids = tst_get_free_pids() / 2.1;
- nr_msgqs -= get_used_msgqueues();
- if (nr_msgqs <= 0) {
- tst_resm(TBROK,
- "Max number of message queues already used, cannot create more.");
- cleanup();
- }
+ avail_msg = MIN(free_msgs, free_pids);
+ if (!avail_msg)
+ tst_brk(TCONF, "Unavailable messages slots");
- /*
- * Since msgmni scales to the memory size, it may reach huge values
- * that are not necessary for this test.
- * That's why we define NR_MSGQUEUES as a high boundary for it.
- */
- MSGMNI = MIN(nr_msgqs, NR_MSGQUEUES);
+ tst_res(TINFO, "Available messages slots: %d", avail_msg);
+
+ if (tst_parse_int(str_num_messages, &num_messages, 1, avail_msg))
+ tst_brk(TBROK, "Invalid number of messages '%s'", str_num_messages);
+
+ if (tst_parse_int(str_num_iterations, &num_iterations, 1, MAXNREPS))
+ tst_brk(TBROK, "Invalid number of messages iterations '%s'", str_num_iterations);
+
+ ipc_data = SAFE_MMAP(
+ NULL,
+ sizeof(struct sysv_data) * num_messages,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+
+ stop = SAFE_MMAP(
+ NULL,
+ sizeof(int),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+
+ reset_messages();
}
-void cleanup(void)
+static void cleanup(void)
{
- int status;
+ if (!ipc_data)
+ return;
-#ifdef DEBUG
- tst_resm(TINFO, "Removing the message queue");
-#endif
- (void)msgctl(tid, IPC_RMID, NULL);
- if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
- (void)msgctl(tid, IPC_RMID, NULL);
- tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
+ for (int pos = 0; pos < num_messages; pos++) {
+ struct sysv_data *buff = &ipc_data[pos];
+ if (buff->id != -1)
+ SAFE_MSGCTL(buff->id, IPC_RMID, NULL);
}
- tst_rmdir();
+ SAFE_MUNMAP(ipc_data, sizeof(struct sysv_data) * num_messages);
+ SAFE_MUNMAP((void *)stop, sizeof(int));
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .max_runtime = 180,
+ .options = (struct tst_option[]) {
+ {"n:", &str_num_messages, "Number of messages to send (default: 1000)"},
+ {"l:", &str_num_iterations, "Number iterations per message (default: 10000)"},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
deleted file mode 100644
index a0f894b05..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * 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
- *
- * 06/30/2001 Port to Linux nsharoff@us.ibm.com
- * 11/11/2002 Port to LTP dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- */
-
-#define _XOPEN_SOURCE 500
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress02";
-int TST_TOTAL = 1;
-
-#define MAXNREPS 1000
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNKIDS 10
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int rkidarray[MAXNKIDS];
-static int wkidarray[MAXNKIDS];
-static int tid;
-static int nprocs, nreps, nkids, MSGMNI;
-static int procstat;
-
-void setup(void);
-void cleanup(void);
-
-static void term(int);
-static int dotest(key_t, int);
-static void cleanup_msgqueue(int i, int tid);
-
-static char *opt_nprocs;
-static char *opt_nkids;
-static char *opt_nreps;
-
-static option_t options[] = {
- {"n:", NULL, &opt_nprocs},
- {"c:", NULL, &opt_nkids},
- {"l:", NULL, &opt_nreps},
- {NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
- printf(" -n Number of processes\n");
- printf(" -c Number of read/write child pairs\n");
- printf(" -l Number of iterations\n");
-}
-
-int main(int argc, char **argv)
-{
- int i, j, ok, pid;
- int count, status;
-
- tst_parse_opts(argc, argv, options, usage);
-
- setup();
-
- nreps = MAXNREPS;
- nprocs = MSGMNI;
- nkids = MAXNKIDS;
-
- if (opt_nreps) {
- nreps = atoi(opt_nreps);
- if (nreps > MAXNREPS) {
- tst_resm(TINFO,
- "Requested number of iterations too large, "
- "setting to Max. of %d", MAXNREPS);
- nreps = MAXNREPS;
- }
- }
-
- if (opt_nprocs) {
- nprocs = atoi(opt_nprocs);
- if (nprocs > MSGMNI) {
- tst_resm(TINFO,
- "Requested number of processes too large, "
- "setting to Max. of %d", MSGMNI);
- nprocs = MSGMNI;
- }
- }
-
- if (opt_nkids) {
- nkids = atoi(opt_nkids);
- if (nkids > MAXNKIDS) {
- tst_resm(TINFO,
- "Requested number of read/write pairs too "
- "large, setting to Max. of %d", MAXNKIDS);
- nkids = MAXNKIDS;
- }
- }
-
- procstat = 0;
- srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
- tid = -1;
-
- /* Setup signal handleing routine */
- if (sigset(SIGTERM, term) == SIG_ERR) {
- tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
- }
- /* Set up array of unique keys for use in allocating message
- * queues
- */
- for (i = 0; i < nprocs; i++) {
- ok = 1;
- do {
- /* Get random key */
- keyarray[i] = (key_t) lrand48();
- /* Make sure key is unique and not private */
- if (keyarray[i] == IPC_PRIVATE) {
- ok = 0;
- continue;
- }
- for (j = 0; j < i; j++) {
- if (keyarray[j] == keyarray[i]) {
- ok = 0;
- break;
- }
- ok = 1;
- }
- } while (ok == 0);
- }
- /* Fork a number of processes (nprocs), each of which will
- * create a message queue with several (nkids) reader/writer
- * pairs which will read and write a number (iterations)
- * of random length messages with specific values (keys).
- */
-
- for (i = 0; i < nprocs; i++) {
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- tst_brkm(TFAIL,
- NULL,
- "\tFork failed (may be OK if under stress)");
- }
- /* Child does this */
- if (pid == 0) {
- procstat = 1;
- exit(dotest(keyarray[i], i));
- }
- pidarray[i] = pid;
- }
-
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != PASS) {
- tst_brkm(TFAIL, NULL,
- "Child exit status = %d",
- status >> 8);
- }
- count++;
- } else {
- if (errno != EINTR) {
- break;
- }
-#ifdef DEBUG
- tst_resm(TINFO, "Signal detected during wait");
-#endif
- }
- }
- /* Make sure proper number of children exited */
- if (count != nprocs) {
- tst_brkm(TFAIL,
- NULL,
- "Wrong number of children exited, Saw %d, Expected %d",
- count, nprocs);
- }
-
- tst_resm(TPASS, "Test ran successfully!");
-
- cleanup();
- tst_exit();
-}
-
-static void cleanup_msgqueue(int i, int tid)
-{
- /*
- * Decrease the value of i by 1 because it
- * is getting incremented even if the fork
- * is failing.
- */
-
- i--;
- /*
- * Kill all children & free message queue.
- */
- for (; i >= 0; i--) {
- (void)kill(rkidarray[i], SIGKILL);
- (void)kill(wkidarray[i], SIGKILL);
- }
-
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- tst_brkm(TFAIL | TERRNO, NULL, "Msgctl error in cleanup");
- }
-}
-
-static int dotest(key_t key, int child_process)
-{
- int id, pid;
- int i, count, status, exit_status;
-
- sighold(SIGTERM);
- if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) {
- printf("msgget() error in child %d: %s\n",
- child_process, strerror(errno));
- return FAIL;
- }
- tid = id;
- sigrelse(SIGTERM);
-
- exit_status = PASS;
-
- for (i = 0; i < nkids; i++) {
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("Fork failure in the first child of child group %d\n",
- child_process);
- cleanup_msgqueue(i, tid);
- return FAIL;
- }
- /* First child does this */
- if (pid == 0) {
- procstat = 2;
- exit(doreader(key, tid, getpid(),
- child_process, nreps));
- }
- rkidarray[i] = pid;
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("Fork failure in the second child of child group %d\n",
- child_process);
- /*
- * Kill the reader child process
- */
- (void)kill(rkidarray[i], SIGKILL);
-
- cleanup_msgqueue(i, tid);
- return FAIL;
- }
- /* Second child does this */
- if (pid == 0) {
- procstat = 2;
- exit(dowriter(key, tid, rkidarray[i],
- child_process, nreps));
- }
- wkidarray[i] = pid;
- }
- /* Parent does this */
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != PASS) {
- printf("Child exit status = %d from child group %d\n",
- status >> 8, child_process);
- for (i = 0; i < nkids; i++) {
- kill(rkidarray[i], SIGTERM);
- kill(wkidarray[i], SIGTERM);
- }
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- printf("msgctl() error: %s\n",
- strerror(errno));
- }
- return FAIL;
- }
- count++;
- } else {
- if (errno != EINTR) {
- break;
- }
- }
- }
- /* Make sure proper number of children exited */
- if (count != (nkids * 2)) {
- printf("Wrong number of children exited in child group %d, saw %d, expected %d\n",
- child_process, count, (nkids * 2));
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- printf("msgctl() error: %s\n", strerror(errno));
- }
- return FAIL;
- }
- if (msgctl(id, IPC_RMID, 0) < 0) {
- printf("msgctl() failure in child group %d: %s\n",
- child_process, strerror(errno));
- return FAIL;
- }
- return exit_status;
-}
-
-static void term(int sig LTP_ATTRIBUTE_UNUSED)
-{
- int i;
-
- if (procstat == 0) {
-#ifdef DEBUG
- tst_resm(TINFO, "SIGTERM signal received, test killing kids");
-#endif
- for (i = 0; i < nprocs; i++) {
- if (pidarray[i] > 0) {
- if (kill(pidarray[i], SIGTERM) < 0) {
- printf("Kill failed to kill child %d",
- i);
- exit(FAIL);
- }
- }
- }
- return;
- }
-
- if (procstat == 2) {
- fflush(stdout);
- exit(PASS);
- }
-
- if (tid == -1) {
- exit(FAIL);
- }
- for (i = 0; i < nkids; i++) {
- if (rkidarray[i] > 0)
- kill(rkidarray[i], SIGTERM);
- if (wkidarray[i] > 0)
- kill(wkidarray[i], SIGTERM);
- }
-}
-
-void setup(void)
-{
- int nr_msgqs;
-
- tst_tmpdir();
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- nr_msgqs = get_max_msgqueues();
- if (nr_msgqs < 0)
- cleanup();
-
- nr_msgqs -= get_used_msgqueues();
- if (nr_msgqs <= 0) {
- tst_resm(TBROK,
- "Max number of message queues already used, cannot create more.");
- cleanup();
- }
-
- /*
- * Since msgmni scales to the memory size, it may reach huge values
- * that are not necessary for this test.
- * That's why we define NR_MSGQUEUES as a high boundary for it.
- */
- MSGMNI = MIN(nr_msgqs, NR_MSGQUEUES);
-}
-
-void cleanup(void)
-{
- int status;
-
-#ifdef DEBUG
- tst_resm(TINFO, "Removing the message queue");
-#endif
- fflush(stdout);
- (void)msgctl(tid, IPC_RMID, NULL);
- if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
- (void)msgctl(tid, IPC_RMID, NULL);
- tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
- }
-
- fflush(stdout);
- tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
deleted file mode 100644
index aa37d9058..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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
- *
- * 06/30/2001 Port to Linux nsharoff@us.ibm.com
- * 11/06/2002 Port to LTP dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- * Same as msgstress01 but gets the actual msgmni value under procfs.
- */
-
-#define _XOPEN_SOURCE 500
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <values.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress03";
-int TST_TOTAL = 1;
-
-#define MAXNPROCS 10000 /*These should be sufficient */
-#define MAXNREPS 10000 /*Else they srewup the system un-necessarily */
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int tid;
-static int MSGMNI, nprocs, nreps;
-static int procstat;
-static int mykid;
-
-void setup(void);
-void cleanup(void);
-
-static int dotest(key_t key, int child_process);
-static void sig_handler(int signo);
-
-static char *opt_nprocs;
-static char *opt_nreps;
-
-static option_t options[] = {
- {"n:", NULL, &opt_nprocs},
- {"l:", NULL, &opt_nreps},
- {NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
- printf(" -n Number of processes\n");
- printf(" -l Number of iterations\n");
-}
-
-int main(int argc, char **argv)
-{
- int i, j, ok, pid, free_pids;
- int count, status;
- struct sigaction act;
-
- tst_parse_opts(argc, argv, options, usage);
-
- setup();
-
- nreps = MAXNREPS;
- nprocs = MSGMNI;
-
- if (opt_nreps) {
- nreps = atoi(opt_nreps);
- if (nreps > MAXNREPS) {
- tst_resm(TINFO,
- "Requested number of iterations too large, "
- "setting to Max. of %d", MAXNREPS);
- nreps = MAXNREPS;
- }
- }
-
- if (opt_nprocs) {
- nprocs = atoi(opt_nprocs);
- if (nprocs > MSGMNI) {
- tst_resm(TINFO,
- "Requested number of processes too large, "
- "setting to Max. of %d", MSGMNI);
- nprocs = MSGMNI;
- }
- }
-
- free_pids = tst_get_free_pids(cleanup);
- /* Each forked child forks once, take it into account here. */
- if (nprocs * 2 >= free_pids) {
- tst_resm(TINFO,
- "Requested number of processes higher than limit (%d > %d), "
- "setting to %d", nprocs * 2, free_pids, free_pids);
- nprocs = free_pids / 2;
- }
-
- srand(getpid());
- tid = -1;
-
- /* Setup signal handling routine */
- memset(&act, 0, sizeof(act));
- act.sa_handler = sig_handler;
- sigemptyset(&act.sa_mask);
- sigaddset(&act.sa_mask, SIGTERM);
- if (sigaction(SIGTERM, &act, NULL) < 0) {
- tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
- }
- /* Set up array of unique keys for use in allocating message
- * queues
- */
- for (i = 0; i < nprocs; i++) {
- ok = 1;
- do {
- /* Get random key */
- keyarray[i] = (key_t) rand();
- /* Make sure key is unique and not private */
- if (keyarray[i] == IPC_PRIVATE) {
- ok = 0;
- continue;
- }
- for (j = 0; j < i; j++) {
- if (keyarray[j] == keyarray[i]) {
- ok = 0;
- break;
- }
- ok = 1;
- }
- } while (ok == 0);
- }
-
- /* Fork a number of processes, each of which will
- * create a message queue with one reader/writer
- * pair which will read and write a number (iterations)
- * of random length messages with specific values.
- */
-
- for (i = 0; i < nprocs; i++) {
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- tst_brkm(TFAIL,
- NULL,
- "\tFork failed (may be OK if under stress)");
- }
- /* Child does this */
- if (pid == 0) {
- procstat = 1;
- exit(dotest(keyarray[i], i));
- }
- pidarray[i] = pid;
- }
-
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != 0) {
- tst_brkm(TFAIL, NULL,
- "Child exit status = %d",
- status >> 8);
- }
- count++;
- } else {
- if (errno != EINTR) {
- break;
- }
-#ifdef DEBUG
- tst_resm(TINFO, "Signal detected during wait");
-#endif
- }
- }
- /* Make sure proper number of children exited */
- if (count != nprocs) {
- tst_brkm(TFAIL,
- NULL,
- "Wrong number of children exited, Saw %d, Expected %d",
- count, nprocs);
- }
-
- tst_resm(TPASS, "Test ran successfully!");
-
- cleanup();
- tst_exit();
-}
-
-static int dotest(key_t key, int child_process)
-{
- int id, pid;
- int ret, status;
-
- sighold(SIGTERM);
- TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
- if (TEST_RETURN < 0) {
- printf("msgget() error in child %d: %s\n",
- child_process, strerror(TEST_ERRNO));
- return FAIL;
- }
- tid = id = TEST_RETURN;
- sigrelse(SIGTERM);
-
- fflush(stdout);
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("Fork failed (may be OK if under stress)\n");
- TEST(msgctl(tid, IPC_RMID, 0));
- if (TEST_RETURN < 0) {
- printf("msgctl() error in cleanup: %s\n",
- strerror(TEST_ERRNO));
- }
- return FAIL;
- }
- if (pid == 0)
- exit(doreader(key, id, 1, child_process, nreps));
-
- mykid = pid;
- procstat = 2;
- ret = dowriter(key, id, 1, child_process, nreps);
- wait(&status);
-
- if (ret != PASS)
- exit(FAIL);
-
- if ((!WIFEXITED(status) || (WEXITSTATUS(status) != PASS)))
- exit(FAIL);
-
- TEST(msgctl(id, IPC_RMID, 0));
- if (TEST_RETURN < 0) {
- printf("msgctl() failed: %s\n",
- strerror(TEST_ERRNO));
- return FAIL;
- }
- return PASS;
-}
-
-static void sig_handler(int signo LTP_ATTRIBUTE_UNUSED)
-{
-}
-
-void setup(void)
-{
- int nr_msgqs;
-
- tst_tmpdir();
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- nr_msgqs = get_max_msgqueues();
- if (nr_msgqs < 0)
- cleanup();
-
- MSGMNI = nr_msgqs - get_used_msgqueues();
- if (MSGMNI > MAXNPROCS)
- MSGMNI = MAXNPROCS;
- if (MSGMNI <= 0) {
- tst_resm(TBROK,
- "Max number of message queues already used, cannot create more.");
- cleanup();
- }
-}
-
-void cleanup(void)
-{
- int status;
-
-#ifdef DEBUG
- tst_resm(TINFO, "Removing the message queue");
-#endif
- (void)msgctl(tid, IPC_RMID, NULL);
- if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
- (void)msgctl(tid, IPC_RMID, NULL);
- tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
- }
-
- tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c
deleted file mode 100644
index b9ebf9035..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * 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
- *
- * 06/30/2001 Port to Linux nsharoff@us.ibm.com
- * 11/11/2002 Port to LTP dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- * Same as msgstress02 but gets the actual msgmni value under procfs.
- */
-
-#define _XOPEN_SOURCE 500
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress04";
-int TST_TOTAL = 1;
-
-#define MAXNREPS 1000
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNKIDS 10
-#define DEFNKIDS 2
-
-static int maxnkids = MAXNKIDS; /* Used if pid_max is exceeded */
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int rkidarray[MAXNKIDS];
-static int wkidarray[MAXNKIDS];
-static int tid;
-static int nprocs, nreps, nkids, MSGMNI;
-static int maxnprocs;
-static int procstat;
-
-void setup(void);
-void cleanup(void);
-
-static void term(int);
-static int dotest(key_t, int);
-static void dotest_iteration(int off);
-static void cleanup_msgqueue(int i, int tid);
-
-static char *opt_maxnprocs;
-static char *opt_nkids;
-static char *opt_nreps;
-
-static option_t options[] = {
- {"n:", NULL, &opt_maxnprocs},
- {"c:", NULL, &opt_nkids},
- {"l:", NULL, &opt_nreps},
- {NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
- printf(" -n Number of processes\n");
- printf(" -c Number of read/write child pairs\n");
- printf(" -l Number of iterations\n");
-}
-
-
-int main(int argc, char **argv)
-{
- int i, j, ok;
-
- tst_parse_opts(argc, argv, options, usage);
-
- setup();
-
- nreps = MAXNREPS;
- nkids = MAXNKIDS;
-
- if (opt_nreps) {
- nreps = atoi(opt_nreps);
- if (nreps > MAXNREPS) {
- tst_resm(TINFO,
- "Requested number of iterations too large, "
- "setting to Max. of %d", MAXNREPS);
- nreps = MAXNREPS;
- }
- }
-
- if (opt_nkids) {
- nkids = atoi(opt_nkids);
- if (nkids > MAXNKIDS) {
- tst_resm(TINFO,
- "Requested number of read/write pairs too "
- "large, setting to Max. of %d", MAXNKIDS);
- nkids = MAXNKIDS;
- }
- }
-
-
- if (opt_maxnprocs) {
- if (atoi(opt_maxnprocs) > maxnprocs) {
- tst_resm(TINFO,
- "Requested number of processes too large, "
- "setting to Max. of %d", MSGMNI);
- } else {
- maxnprocs = atoi(opt_maxnprocs);
- }
- }
-
- procstat = 0;
- srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
- tid = -1;
-
- /* Setup signal handling routine */
- if (sigset(SIGTERM, term) == SIG_ERR)
- tst_brkm(TFAIL, cleanup, "Sigset SIGTERM failed");
-
- /* Set up array of unique keys for use in allocating message
- * queues
- */
- for (i = 0; i < MSGMNI; i++) {
- ok = 1;
- do {
- /* Get random key */
- keyarray[i] = (key_t) lrand48();
- /* Make sure key is unique and not private */
- if (keyarray[i] == IPC_PRIVATE) {
- ok = 0;
- continue;
- }
- for (j = 0; j < i; j++) {
- if (keyarray[j] == keyarray[i]) {
- ok = 0;
- break;
- }
- ok = 1;
- }
- } while (ok == 0);
- }
- /* Fork a number of processes, each of which will
- * create a message queue with several (nkids) reader/writer
- * pairs which will read and write a number (iterations)
- * of random length messages with specific values (keys).
- *
- * We do not fork more than maxnprocs at a time and
- * we fork until all the message queues get used.
- */
-
- if (MSGMNI <= maxnprocs) {
- nprocs = MSGMNI;
- dotest_iteration(0);
- } else {
- for (i = 0; i < (MSGMNI / maxnprocs); i++) {
- nprocs = maxnprocs;
- dotest_iteration(i * maxnprocs);
- }
-
- nprocs = MSGMNI % maxnprocs;
- dotest_iteration(i * maxnprocs);
- }
-
- tst_resm(TPASS, "Test ran successfully!");
-
- cleanup();
- tst_exit();
-}
-
-static void dotest_iteration(int off)
-{
- key_t key;
- int i, count, status;
- pid_t pid;
-
- memset(pidarray, 0, sizeof(pidarray));
-
- for (i = 0; i < nprocs; i++) {
- key = keyarray[off + i];
-
- if ((pid = FORK_OR_VFORK()) < 0)
- tst_brkm(TFAIL, cleanup,
- "Fork failed (may be OK if under stress)");
-
- /* Child does this */
- if (pid == 0) {
- procstat = 1;
- exit(dotest(key, i));
- }
- pidarray[i] = pid;
- }
-
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != PASS)
- tst_brkm(TFAIL, cleanup,
- "Child exit status = %d", status >> 8);
- count++;
- } else {
- if (errno != EINTR) {
- break;
- }
-#ifdef DEBUG
- tst_resm(TINFO, "Signal detected during wait");
-#endif
- }
- }
- /* Make sure proper number of children exited */
- if (count != nprocs)
- tst_brkm(TFAIL, cleanup,
- "Wrong number of children exited, Saw %d, Expected %d",
- count, nprocs);
-}
-
-static void cleanup_msgqueue(int i, int tid)
-{
- /*
- * Decrease the value of i by 1 because it
- * is getting incremented even if the fork
- * is failing.
- */
-
- i--;
- /*
- * Kill all children & free message queue.
- */
- for (; i >= 0; i--) {
- (void)kill(rkidarray[i], SIGKILL);
- (void)kill(wkidarray[i], SIGKILL);
- }
-
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- printf("Msgctl error in cleanup_msgqueue %d\n", errno);
- exit(FAIL);
- }
-}
-
-static int dotest(key_t key, int child_process)
-{
- int id, pid;
- int i, count, status, exit_status;
-
- sighold(SIGTERM);
- if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) {
- printf("msgget() error in child %d: %s\n",
- child_process, strerror(errno));
- return FAIL;
- }
- tid = id;
- sigrelse(SIGTERM);
-
- exit_status = PASS;
-
- for (i = 0; i < nkids; i++) {
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("Fork failure in the first child of child group %d\n",
- child_process);
- cleanup_msgqueue(i, tid);
- return FAIL;
- }
- /* First child does this */
- if (pid == 0) {
- procstat = 2;
- exit(doreader(key, tid, getpid(),
- child_process, nreps));
- }
- rkidarray[i] = pid;
- if ((pid = FORK_OR_VFORK()) < 0) {
- printf("Fork failure in the second child of child group %d\n",
- child_process);
- /*
- * Kill the reader child process
- */
- (void)kill(rkidarray[i], SIGKILL);
-
- cleanup_msgqueue(i, tid);
- return FAIL;
- }
- /* Second child does this */
- if (pid == 0) {
- procstat = 2;
- exit(dowriter(key, tid, rkidarray[i],
- child_process, nreps));
- }
- wkidarray[i] = pid;
- }
- /* Parent does this */
- count = 0;
- while (1) {
- if ((wait(&status)) > 0) {
- if (status >> 8 != PASS) {
- printf("Child exit status = %d from child group %d\n",
- status >> 8, child_process);
- for (i = 0; i < nkids; i++) {
- kill(rkidarray[i], SIGTERM);
- kill(wkidarray[i], SIGTERM);
- }
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- printf("msgctl() error: %s\n",
- strerror(errno));
- }
- return FAIL;
- }
- count++;
- } else {
- if (errno != EINTR) {
- break;
- }
- }
- }
- /* Make sure proper number of children exited */
- if (count != (nkids * 2)) {
- printf("Wrong number of children exited in child group %d, saw %d, expected %d\n",
- child_process, count, (nkids * 2));
- if (msgctl(tid, IPC_RMID, 0) < 0) {
- printf("msgctl() error: %s\n", strerror(errno));
- }
- return FAIL;
- }
- if (msgctl(id, IPC_RMID, 0) < 0) {
- printf("msgctl() failure in child group %d: %s\n",
- child_process, strerror(errno));
- return FAIL;
- }
- return exit_status;
-}
-
-/* ARGSUSED */
-static void term(int sig LTP_ATTRIBUTE_UNUSED)
-{
- int i;
-
- if (procstat == 0) {
-#ifdef DEBUG
- tst_resm(TINFO, "SIGTERM signal received, test killing kids");
-#endif
- for (i = 0; i < nprocs; i++) {
- if (pidarray[i] > 0) {
- if (kill(pidarray[i], SIGTERM) < 0) {
- tst_resm(TBROK,
- "Kill failed to kill child %d",
- i);
- exit(FAIL);
- }
- }
- }
- return;
- }
-
- if (procstat == 2) {
- exit(PASS);
- }
-
- if (tid == -1) {
- exit(FAIL);
- }
- for (i = 0; i < nkids; i++) {
- if (rkidarray[i] > 0)
- kill(rkidarray[i], SIGTERM);
- if (wkidarray[i] > 0)
- kill(wkidarray[i], SIGTERM);
- }
-}
-
-void setup(void)
-{
- int nr_msgqs, free_pids;
-
- tst_tmpdir();
- /* You will want to enable some signal handling so you can capture
- * unexpected signals like SIGSEGV.
- */
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to
- * fork the test with the -c option. You want to make sure you do this
- * before you create your temporary directory.
- */
- TEST_PAUSE;
-
- nr_msgqs = get_max_msgqueues();
- if (nr_msgqs < 0)
- tst_brkm(TBROK, cleanup, "get_max_msgqueues() failed");
-
- MSGMNI = nr_msgqs - get_used_msgqueues();
- if (MSGMNI <= 0)
- tst_brkm(TBROK, cleanup,
- "Max number of message queues already used, cannot create more.");
-
- tst_resm(TINFO, "Found %d available message queues", MSGMNI);
-
- free_pids = tst_get_free_pids(cleanup);
- /* We don't use more than a half of available pids.
- * For each child we fork up to 2*maxnkids grandchildren. */
- maxnprocs = (free_pids / 2) / (1 + 2 * maxnkids);
-
- if (!maxnprocs)
- tst_brkm(TBROK, cleanup, "Not enough free pids");
-
- tst_resm(TINFO, "Using upto %d pids", free_pids / 2);
-}
-
-void cleanup(void)
-{
- int status;
-
- /*
- * Remove the message queue from the system
- */
-#ifdef DEBUG
- tst_resm(TINFO, "Removing the message queue");
-#endif
- (void)msgctl(tid, IPC_RMID, NULL);
- if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
- (void)msgctl(tid, IPC_RMID, NULL);
- tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
- }
-
- tst_rmdir();
-}
--
2.35.3
More information about the ltp
mailing list