@@ -224,13 +224,115 @@ docker_e2e_run_with_harness() {
224224 local run_status=0
225225 local cid_dir
226226 local cidfile
227+ local docker_run_pid=" "
228+ local harness_stdin_fd=" "
229+ local cleanup_done=0
230+ local previous_int_trap
231+ local previous_term_trap
232+ local previous_hup_trap
227233 cid_dir=" $( mktemp -d " ${TMPDIR:-/ tmp} /openclaw-docker-e2e-container.XXXXXX" ) "
228234 cidfile=" $cid_dir /container.cid"
229- docker_e2e_docker_run_cmd run --rm --cidfile " $cidfile " " ${DOCKER_E2E_HARNESS_ARGS[@]} " " $@ " ||
230- run_status=" $? "
231- docker_e2e_cleanup_container_cidfile " $cidfile "
232- rmdir " $cid_dir " 2> /dev/null || true
233- docker_e2e_cleanup_package_mount_args
235+ previous_int_trap=" $( trap -p INT || true) "
236+ previous_term_trap=" $( trap -p TERM || true) "
237+ previous_hup_trap=" $( trap -p HUP || true) "
238+ restore_harness_traps () {
239+ if [ -n " $previous_int_trap " ]; then
240+ eval " $previous_int_trap "
241+ else
242+ trap - INT
243+ fi
244+ if [ -n " $previous_term_trap " ]; then
245+ eval " $previous_term_trap "
246+ else
247+ trap - TERM
248+ fi
249+ if [ -n " $previous_hup_trap " ]; then
250+ eval " $previous_hup_trap "
251+ else
252+ trap - HUP
253+ fi
254+ }
255+ docker_e2e_harness_descendant_pids () {
256+ local parent_pid=" $1 "
257+ local child_pid
258+ for child_pid in $( pgrep -P " $parent_pid " 2> /dev/null || true) ; do
259+ docker_e2e_harness_descendant_pids " $child_pid "
260+ printf ' %s\n' " $child_pid "
261+ done
262+ }
263+ terminate_harness_docker_run () {
264+ [ -n " $docker_run_pid " ] || return 0
265+ kill -0 " $docker_run_pid " 2> /dev/null || return 0
266+ local descendant_pids
267+ descendant_pids=" $( docker_e2e_harness_descendant_pids " $docker_run_pid " ) "
268+ if [ -n " $descendant_pids " ]; then
269+ kill -TERM $descendant_pids 2> /dev/null || true
270+ fi
271+ kill -TERM " $docker_run_pid " 2> /dev/null || true
272+ local grace_seconds=" ${OPENCLAW_DOCKER_E2E_CONTAINER_TERM_GRACE_SECONDS:- 10} "
273+ if ! [[ " $grace_seconds " =~ ^[0-9]+$ ]] || [ " $grace_seconds " -lt 1 ]; then
274+ grace_seconds=" 10"
275+ else
276+ grace_seconds=" $(( 10 #$grace_seconds )) "
277+ fi
278+ local wait_attempt
279+ for wait_attempt in $( seq 1 " $(( grace_seconds * 10 )) " ) ; do
280+ if ! kill -0 " $docker_run_pid " 2> /dev/null; then
281+ return 0
282+ fi
283+ /bin/sleep 0.1
284+ done
285+ descendant_pids=" $( docker_e2e_harness_descendant_pids " $docker_run_pid " ) "
286+ if [ -n " $descendant_pids " ]; then
287+ kill -KILL $descendant_pids 2> /dev/null || true
288+ fi
289+ kill -KILL " $docker_run_pid " 2> /dev/null || true
290+ }
291+ cleanup_harness_run () {
292+ local cleanup_status=" ${1:- $? } "
293+ local exit_after_cleanup=" ${2:- 0} "
294+ if [ " $cleanup_done " = " 1" ]; then
295+ if [ " $exit_after_cleanup " = " 1" ]; then
296+ exit " $cleanup_status "
297+ fi
298+ return " $cleanup_status "
299+ fi
300+ cleanup_done=1
301+ trap - INT TERM HUP
302+ terminate_harness_docker_run
303+ wait " $docker_run_pid " 2> /dev/null || true
304+ docker_e2e_cleanup_container_cidfile " $cidfile "
305+ rmdir " $cid_dir " 2> /dev/null || true
306+ docker_e2e_cleanup_package_mount_args
307+ if [ -n " $harness_stdin_fd " ]; then
308+ exec {harness_stdin_fd}< & -
309+ harness_stdin_fd=" "
310+ fi
311+ restore_harness_traps
312+ if [ " $exit_after_cleanup " = " 1" ]; then
313+ exit " $cleanup_status "
314+ fi
315+ return " $cleanup_status "
316+ }
317+ trap ' cleanup_harness_run 130 1' INT
318+ trap ' cleanup_harness_run 143 1' TERM
319+ trap ' cleanup_harness_run 129 1' HUP
320+ exec {harness_stdin_fd}< & 0
321+ docker_e2e_docker_run_cmd run --rm --cidfile " $cidfile " " ${DOCKER_E2E_HARNESS_ARGS[@]} " " $@ " < & $harness_stdin_fd &
322+ docker_run_pid=" $! "
323+ local had_errexit=0
324+ case " $- " in
325+ * e* )
326+ had_errexit=1
327+ ;;
328+ esac
329+ set +e
330+ wait " $docker_run_pid "
331+ run_status=" $? "
332+ if [ " $had_errexit " = " 1" ]; then
333+ set -e
334+ fi
335+ cleanup_harness_run 0
234336 return " $run_status "
235337}
236338
0 commit comments