Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
steam-runtime-tools
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Analyze
Contributor analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
steamrt
steam-runtime-tools
Commits
943eff90
Commit
943eff90
authored
4 years ago
by
Simon McVittie
Browse files
Options
Downloads
Patches
Plain Diff
adverb, utils: Factor out pv_wait_for_child_processes()
Signed-off-by:
Simon McVittie
<
smcv@collabora.com
>
parent
dc513da7
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/adverb.c
+22
-45
22 additions, 45 deletions
src/adverb.c
src/utils.c
+87
-0
87 additions, 0 deletions
src/utils.c
src/utils.h
+5
-0
5 additions, 0 deletions
src/utils.h
with
114 additions
and
45 deletions
src/adverb.c
+
22
−
45
View file @
943eff90
...
...
@@ -534,53 +534,30 @@ main (int argc,
/* If the child writes to stdout and closes it, don't interfere */
g_clear_pointer
(
&
original_stdout
,
fclose
);
while
(
1
)
{
pid_t
died
=
wait
(
&
wait_status
)
;
/* Reap child processes until child_pid exits */
if
(
!
pv_wait_for_child_processes
(
child_pid
,
&
wait_status
,
error
))
goto
out
;
if
(
died
<
0
)
{
if
(
errno
==
EINTR
)
{
continue
;
}
else
if
(
errno
==
ECHILD
)
{
g_debug
(
"No more child processes, exiting"
);
break
;
}
else
{
glnx_throw_errno_prefix
(
error
,
"wait"
);
goto
out
;
}
}
else
if
(
died
==
child_pid
)
{
if
(
WIFEXITED
(
wait_status
))
{
ret
=
WEXITSTATUS
(
wait_status
);
g_debug
(
"Command exited with status %d"
,
ret
);
}
else
if
(
WIFSIGNALED
(
wait_status
))
{
ret
=
128
+
WTERMSIG
(
wait_status
);
g_debug
(
"Command killed by signal %d"
,
ret
-
128
);
}
else
{
ret
=
EX_SOFTWARE
;
g_debug
(
"Command terminated in an unknown way (wait status %d)"
,
wait_status
);
}
}
else
{
g_debug
(
"Indirect child %lld exited with wait status %d"
,
(
long
long
)
died
,
wait_status
);
g_warn_if_fail
(
opt_subreaper
);
}
if
(
WIFEXITED
(
wait_status
))
{
ret
=
WEXITSTATUS
(
wait_status
);
g_debug
(
"Command exited with status %d"
,
ret
);
}
else
if
(
WIFSIGNALED
(
wait_status
))
{
ret
=
128
+
WTERMSIG
(
wait_status
);
g_debug
(
"Command killed by signal %d"
,
ret
-
128
);
}
else
{
ret
=
EX_SOFTWARE
;
g_debug
(
"Command terminated in an unknown way (wait status %d)"
,
wait_status
);
}
/* Wait for the other child processes, if any */
if
(
!
pv_wait_for_child_processes
(
0
,
NULL
,
error
))
goto
out
;
out:
global_locks
=
NULL
;
...
...
This diff is collapsed.
Click to expand it.
src/utils.c
+
87
−
0
View file @
943eff90
...
...
@@ -23,6 +23,8 @@
#include
"utils.h"
#include
<ftw.h>
#include
<sys/types.h>
#include
<sys/wait.h>
#include
<glib.h>
#include
<glib/gstdio.h>
...
...
@@ -575,3 +577,88 @@ pv_get_random_uuid (GError **error)
return
g_steal_pointer
(
&
contents
);
}
/**
* pv_wait_for_child_processes:
* @main_process: process for which we will report wait-status;
* zero or negative if there is no main process
* @wait_status_out: (out): Used to store the wait status of `@main_process`,
* as if from `wait()`, on success
* @error: Used to raise an error on failure
*
* Wait for child processes of this process to exit, until the @main_process
* has exited. If there is no main process, wait until there are no child
* processes at all.
*
* If the process is a subreaper (`PR_SET_CHILD_SUBREAPER`),
* indirect child processes whose parents have exited will be reparented
* to it, so this will have the effect of waiting for all descendants.
*
* If @main_process is positive, return when @main_process has exited.
* Child processes that exited before @main_process will also have been
* "reaped", but child processes that exit after @main_process will not
* (use `pv_wait_for_child_processes (0, &error)` to resume waiting).
*
* If @main_process is zero or negative, wait for all child processes
* to exit.
*
* This function cannot be called in a process that is using
* g_child_watch_source_new() or similar functions, because it waits
* for all child processes regardless of their process IDs, and that is
* incompatible with waiting for individual child processes.
*
* Returns: %TRUE when @main_process has exited, or if @main_process
* is zero or negative and all child processes have exited
*/
gboolean
pv_wait_for_child_processes
(
pid_t
main_process
,
int
*
wait_status_out
,
GError
**
error
)
{
if
(
wait_status_out
!=
NULL
)
*
wait_status_out
=
-
1
;
while
(
1
)
{
int
wait_status
=
-
1
;
pid_t
died
=
wait
(
&
wait_status
);
if
(
died
<
0
)
{
if
(
errno
==
EINTR
)
{
continue
;
}
else
if
(
errno
==
ECHILD
)
{
g_debug
(
"No more child processes"
);
break
;
}
else
{
return
glnx_throw_errno_prefix
(
error
,
"wait"
);
}
}
g_debug
(
"Child %lld exited with wait status %d"
,
(
long
long
)
died
,
wait_status
);
if
(
died
==
main_process
)
{
if
(
wait_status_out
!=
NULL
)
*
wait_status_out
=
wait_status
;
return
TRUE
;
}
}
if
(
main_process
>
0
)
{
g_set_error
(
error
,
G_IO_ERROR
,
G_IO_ERROR_NOT_FOUND
,
"Process %lld was not seen to exit"
,
(
long
long
)
main_process
);
return
FALSE
;
}
return
TRUE
;
}
This diff is collapsed.
Click to expand it.
src/utils.h
+
5
−
0
View file @
943eff90
...
...
@@ -23,6 +23,7 @@
#pragma once
#include
<stdio.h>
#include
<sys/types.h>
#include
<glib.h>
...
...
@@ -60,3 +61,7 @@ void pv_async_signal_safe_error (const char *message,
int
exit_status
)
G_GNUC_NORETURN
;
gchar
*
pv_get_random_uuid
(
GError
**
error
);
gboolean
pv_wait_for_child_processes
(
pid_t
main_process
,
int
*
wait_status_out
,
GError
**
error
);
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment