]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
waitpid: allow to only wait for a specific number of process exits
authorThomas Weißschuh <thomas@t-8ch.de>
Thu, 2 Mar 2023 21:06:31 +0000 (21:06 +0000)
committerThomas Weißschuh <thomas@t-8ch.de>
Thu, 2 Mar 2023 22:12:37 +0000 (22:12 +0000)
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
bash-completion/waitpid
misc-utils/waitpid.1.adoc
misc-utils/waitpid.c
tests/expected/misc/waitpid-count [new file with mode: 0644]
tests/expected/misc/waitpid-count.err [new file with mode: 0644]
tests/ts/misc/waitpid

index 67601bb8f7b7bf6f1bb3edda7a820ac2010e39a5..60ea275afc27d524e48b0d1efd37fb5791ed6032 100644 (file)
@@ -9,6 +9,9 @@ _waitpid_module()
                        COMPREPLY=( $(compgen -W "seconds" -- $cur) )
                        return 0
                        ;;
+               '-c'|'--count')
+                       return 0
+                       ;;
                '-h'|'--help'|'-V'|'--version')
                        return 0
                        ;;
@@ -18,6 +21,7 @@ _waitpid_module()
                        OPTS="--verbose
                                --timeout
                                --exited
+                               --count
                                --help
                                --version"
                        COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
index ea9a7cf5c3ad3615bf02ffe7d496d47df215fd2b..e0dae517ed6fe58a9b86cb351ce6546b8eef6153 100644 (file)
@@ -32,6 +32,9 @@ Maximum wait time.
 *-e*, *--exited*::
 Don't error on already exited PIDs.
 
+*-c*, *--count* _count_::
+Number of process exits to wait for.
+
 include::man-common/help-version.adoc[]
 
 == EXIT STATUS
index f7c5d4166ed8f0e1131c95276ac336bfad27fc26..871a36949e917f3ea91bc4c87c460c5957def236 100644 (file)
@@ -46,6 +46,7 @@
 static bool verbose = false;
 static struct timespec timeout;
 static bool allow_exited = false;
+static size_t count;
 
 static pid_t *parse_pids(size_t n_strings, char * const *strings)
 {
@@ -161,6 +162,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -v, --verbose           be more verbose\n"), out);
        fputs(_(" -t, --timeout=<timeout> wait at most timeout seconds\n"), out);
        fputs(_(" -e, --exited            allow exited PIDs\n"), out);
+       fputs(_(" -c, --count=<count>     number of process exits to wait for\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
        fprintf(out, USAGE_HELP_OPTIONS(25));
@@ -177,12 +179,13 @@ static int parse_options(int argc, char **argv)
                { "verbose", no_argument,       NULL, 'v' },
                { "timeout", required_argument, NULL, 't' },
                { "exited",  no_argument,       NULL, 'e' },
+               { "count",   required_argument, NULL, 'c' },
                { "version", no_argument,       NULL, 'V' },
                { "help",    no_argument,       NULL, 'h' },
                { 0 }
        };
 
-       while ((c = getopt_long (argc, argv, "vVht:e", longopts, NULL)) != -1) {
+       while ((c = getopt_long (argc, argv, "vVht:c:e", longopts, NULL)) != -1) {
                switch (c) {
                case 'v':
                        verbose = true;
@@ -194,6 +197,10 @@ static int parse_options(int argc, char **argv)
                case 'e':
                        allow_exited = true;
                        break;
+               case 'c':
+                       count = str2num_or_err(optarg, 10, _("Invalid count"),
+                                              1, INT64_MAX);
+                       break;
                case 'V':
                        print_version(EXIT_SUCCESS);
                case 'h':
@@ -203,6 +210,10 @@ static int parse_options(int argc, char **argv)
                }
        }
 
+       if (allow_exited && count)
+               errx(EXIT_FAILURE,
+                    _("-e/--exited and -c/--count are incompatible"));
+
        return optind;
 }
 
@@ -220,6 +231,10 @@ int main(int argc, char **argv)
        if (!n_pids)
                errx(EXIT_FAILURE, _("no PIDs specified"));
 
+       if (count && count > n_pids)
+               errx(EXIT_FAILURE,
+                    _("can't want for %zu of %zu PIDs"), count, n_pids);
+
        pid_t *pids = parse_pids(argc - pid_idx, argv + pid_idx);
 
        pidfds = open_pidfds(n_pids, pids);
@@ -229,5 +244,7 @@ int main(int argc, char **argv)
                err_nosys(EXIT_FAILURE, _("could not create epoll"));
 
        active_pids = add_listeners(epoll, n_pids, pidfds, timeoutfd);
+       if (count)
+               active_pids = min(active_pids, count);
        wait_for_exits(epoll, active_pids, pids, pidfds);
 }
diff --git a/tests/expected/misc/waitpid-count b/tests/expected/misc/waitpid-count
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/tests/expected/misc/waitpid-count.err b/tests/expected/misc/waitpid-count.err
new file mode 100644 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
index 599bb47da371577997c2d08b45d89477f543ea62..ae5ab6f928ded41a6f8be9edfecaf97eb21130a3 100755 (executable)
@@ -48,4 +48,12 @@ ts_init_subtest exited
 echo $? >> "$TS_ERRLOG"
 ts_finalize_subtest
 
+ts_init_subtest count
+(sleep 0.2; echo 1 >> "$TS_OUTPUT") &
+BG1="$!"
+
+"$TS_CMD_WAITPID" -c 1 1 "$BG1" >> "$TS_OUTPUT" 2>> "$TS_ERRLOG"
+echo $? >> "$TS_ERRLOG"
+ts_finalize_subtest
+
 ts_finalize