Skip to content

Commit 98b5497

Browse files
authored
fix(spark): propagate exit code of the entrypoint (#1595)
* fix(spark): propagate exit code of the entrypoint * chore: add changelog entry * fix(spark): rewrite run-spark.sh to fit into existing script pattern
1 parent 2dc59e1 commit 98b5497

2 files changed

Lines changed: 48 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Fixed
8+
9+
- spark: Propagate the entrypoint's exit code so failed applications are no longer reported as successful ([#1595]).
10+
711
### Removed
812

913
- omid: remove 1.1.2 ([#1593]).
1014

1115
[#1593]: https://github.com/stackabletech/docker-images/pull/1593
16+
[#1595]: https://github.com/stackabletech/docker-images/pull/1595
1217

1318
## [26.7.0] - 2026-07-21
1419

spark-k8s/stackable/run-spark.sh

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,52 @@
11
#!/bin/bash
22

3-
eval "$_STACKABLE_PRE_HOOK"
4-
5-
# Forward SIGTERM to the Spark entrypoint to support spark JVM's gracefully shutdown.
6-
/stackable/spark/kubernetes/dockerfiles/spark/entrypoint.sh "$@" &
7-
child_pid=$!
3+
prepare_signal_handlers() {
4+
unset term_child_pid
5+
unset term_kill_needed
6+
trap handle_term_signal TERM INT
7+
}
88

9+
# Only ever invoked via the trap installed above.
910
# shellcheck disable=SC2329
10-
_handle_term() {
11-
kill -TERM "$child_pid" 2>/dev/null || true
11+
handle_term_signal() {
12+
if [[ -v term_child_pid ]]; then
13+
kill -TERM "${term_child_pid}" 2>/dev/null || true
14+
else
15+
term_kill_needed="yes"
16+
fi
17+
}
18+
19+
# Waits for the given child and returns *its* exit status.
20+
# A trapped signal makes `wait` return immediately with a status > 128 while the child keeps
21+
# running its shutdown sequence, so in that case wait again instead of taking the interrupted
22+
# status.
23+
wait_for_termination() {
24+
term_child_pid=$1
25+
if [[ -v term_kill_needed ]]; then
26+
kill -TERM "${term_child_pid}" 2>/dev/null || true
27+
fi
28+
while true; do
29+
wait "${term_child_pid}"
30+
term_child_status=$?
31+
if [[ "${term_child_status}" -gt 128 ]] && kill -0 "${term_child_pid}" 2>/dev/null; then
32+
continue
33+
fi
34+
return "${term_child_status}"
35+
done
1236
}
13-
trap _handle_term TERM INT
1437

15-
# `wait` returns immediately when the trap fires; loop until the child is actually gone.
16-
wait "$child_pid"
17-
while kill -0 "$child_pid" 2>/dev/null; do
18-
wait "$child_pid" 2>/dev/null || true
19-
done
20-
result=$?
38+
eval "$_STACKABLE_PRE_HOOK"
39+
40+
# The signal handlers are installed before the child is started, so that a signal arriving in
41+
# between is not lost. SIGTERM is forwarded to the Spark entrypoint to let the Spark JVM shut
42+
# down gracefully.
43+
prepare_signal_handlers
44+
45+
/stackable/spark/kubernetes/dockerfiles/spark/entrypoint.sh "$@" &
46+
47+
result=0
48+
wait_for_termination $! || result=$?
2149

2250
eval "$_STACKABLE_POST_HOOK"
2351

24-
exit $result
52+
exit "${result}"

0 commit comments

Comments
 (0)