1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <stdint.h>
5#include <errno.h>
6#include <err.h>
7#include <pthread.h>
8#include <spawn.h>
9
10extern char **environ;
11
12char * const *newargv;
13
14void usage(void);
15
16void *work(void *);
17
18int main(int argc, char *argv[]) {
19
20    int i, count, threadcount;
21    int ret;
22    pthread_t *threads;
23
24    if (argc < 4) {
25        usage();
26    }
27
28    threadcount = atoi(argv[1]);
29    count = atoi(argv[2]);
30
31    newargv = &argv[3];
32
33    threads = (pthread_t *)calloc(threadcount, sizeof(pthread_t));
34    for (i=0; i < threadcount; i++) {
35        ret = pthread_create(&threads[i], NULL, work, (void *)(intptr_t)count);
36        if (ret) {
37            err(1, "pthread_create");
38        }
39    }
40
41    for (i=0; i < threadcount; i++) {
42        ret = pthread_join(threads[i], NULL);
43        if (ret) {
44            err(1, "pthread_join");
45        }
46    }
47
48    return 0;
49}
50
51void usage(void) {
52    fprintf(stderr, "Usage: %s <threadcount> <count> <program> [<arg1> [<arg2> ...]]\n",
53            getprogname());
54    exit(1);
55}
56
57void *work(void *arg)
58{
59    int count = (int)(intptr_t)arg;
60    int i;
61    int ret;
62    pid_t pid;
63
64    for (i=0; i < count; i++) {
65        ret = posix_spawn(&pid, newargv[0], NULL, NULL, newargv, environ);
66        if (ret != 0) {
67            errc(1, ret, "posix_spawn(%s)", newargv[0]);
68        }
69
70        while (-1 == waitpid(pid, &ret, 0)) {
71            if (errno != EINTR) {
72                err(1, "waitpid(%d)", pid);
73            }
74        }
75
76        if (WIFSIGNALED(ret)) {
77            errx(1, "process exited with signal %d", WTERMSIG(ret));
78        } else if (WIFSTOPPED(ret)) {
79            errx(1, "process stopped with signal %d", WSTOPSIG(ret));
80        } else if (WIFEXITED(ret)) {
81            if (WEXITSTATUS(ret) != 42) {
82                errx(1, "process exited with unexpected exit code %d", WEXITSTATUS(ret));
83            }
84        } else {
85            errx(1, "unknown exit condition %x", ret);
86        }
87    }
88
89    return NULL;
90}
91