mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 00:17:47 +08:00
154 lines
5.2 KiB
Bash
Executable File
154 lines
5.2 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# QingLong 3.0 local completion launcher. Keep this POSIX-only: edge images
|
|
# must not pay for a Node sidecar per task.
|
|
set -u
|
|
umask 077
|
|
|
|
launch_mode=${1-}
|
|
if [ "$#" -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
run_id=${QL3_RECEIPT_RUN_ID-}
|
|
attempt_id=${QL3_RECEIPT_ATTEMPT_ID-}
|
|
callback_sequence=${QL3_RECEIPT_CALLBACK_SEQUENCE-}
|
|
callback_token=${QL3_RECEIPT_CALLBACK_TOKEN-}
|
|
started_at_ms=${QL3_RECEIPT_STARTED_AT_MS-}
|
|
receipt_target=${QL3_RECEIPT_TARGET-}
|
|
receipt_temporary=${QL3_RECEIPT_TEMPORARY-}
|
|
launch_shell=${QL3_LAUNCH_SHELL-}
|
|
launch_shell_command=${QL3_LAUNCH_SHELL_COMMAND-}
|
|
output_quota_fifo=${QL3_OUTPUT_QUOTA_FIFO-}
|
|
output_quota_remaining_bytes=${QL3_OUTPUT_QUOTA_REMAINING_BYTES-}
|
|
output_artifact_id=${QL3_OUTPUT_ARTIFACT_ID-}
|
|
output_maximum_bytes=${QL3_OUTPUT_MAXIMUM_BYTES-}
|
|
output_truncation_target=${QL3_OUTPUT_TRUNCATION_TARGET-}
|
|
output_truncation_temporary=${QL3_OUTPUT_TRUNCATION_TEMPORARY-}
|
|
|
|
# The user process must not inherit the completion capability or journal paths.
|
|
unset QL3_RECEIPT_RUN_ID QL3_RECEIPT_ATTEMPT_ID
|
|
unset QL3_RECEIPT_CALLBACK_SEQUENCE QL3_RECEIPT_CALLBACK_TOKEN
|
|
unset QL3_RECEIPT_STARTED_AT_MS QL3_RECEIPT_TARGET QL3_RECEIPT_TEMPORARY
|
|
unset QL3_LAUNCH_SHELL QL3_LAUNCH_SHELL_COMMAND
|
|
unset QL3_OUTPUT_QUOTA_FIFO QL3_OUTPUT_QUOTA_REMAINING_BYTES
|
|
unset QL3_OUTPUT_ARTIFACT_ID QL3_OUTPUT_MAXIMUM_BYTES
|
|
unset QL3_OUTPUT_TRUNCATION_TARGET QL3_OUTPUT_TRUNCATION_TEMPORARY
|
|
|
|
if ! { [ "$launch_mode" = "argv" ] && [ "$#" -gt 0 ]; } &&
|
|
! { [ "$launch_mode" = "shell" ] && [ -n "$launch_shell" ]; }; then
|
|
exit 125
|
|
fi
|
|
|
|
drain_pid=
|
|
if [ -n "$output_quota_fifo" ]; then
|
|
case "$output_quota_remaining_bytes" in
|
|
''|*[!0-9]*) exit 125 ;;
|
|
esac
|
|
case "$output_maximum_bytes" in
|
|
''|*[!0-9]*) exit 125 ;;
|
|
esac
|
|
if [ -z "$output_artifact_id" ] ||
|
|
[ -z "$output_truncation_target" ] ||
|
|
[ -z "$output_truncation_temporary" ]; then
|
|
exit 125
|
|
fi
|
|
rm -f "$output_truncation_temporary" 2>/dev/null || exit 125
|
|
if ! mkfifo -m 600 "$output_quota_fifo" 2>/dev/null; then
|
|
exit 125
|
|
fi
|
|
|
|
publish_output_truncation() {
|
|
quota_reached=$1
|
|
truncation_observed_at_ms=$(( $(date +%s) * 1000 ))
|
|
truncation_payload="{\"schemaVersion\":1,\"runId\":\"$run_id\",\"attemptId\":\"$attempt_id\",\"logArtifactId\":\"$output_artifact_id\",\"maximumBytes\":$output_maximum_bytes,\"quotaReached\":$quota_reached,\"observedAtMs\":$truncation_observed_at_ms}"
|
|
if (set -C; printf '%s' "$truncation_payload" > "$output_truncation_temporary") 2>/dev/null; then
|
|
sync -f "$output_truncation_temporary" 2>/dev/null || :
|
|
if ln "$output_truncation_temporary" "$output_truncation_target" 2>/dev/null; then
|
|
sync -f "$output_truncation_target" 2>/dev/null || :
|
|
fi
|
|
rm -f "$output_truncation_temporary" 2>/dev/null || :
|
|
sync -f "${output_truncation_target%/*}" 2>/dev/null || :
|
|
fi
|
|
}
|
|
|
|
(
|
|
if [ "$output_quota_remaining_bytes" -gt 0 ]; then
|
|
head -c "$output_quota_remaining_bytes"
|
|
fi
|
|
overflow_bytes=$(wc -c | tr -d '[:space:]') || overflow_bytes=
|
|
case "$overflow_bytes" in
|
|
''|*[!0-9]*) ;;
|
|
0) publish_output_truncation false ;;
|
|
*) publish_output_truncation true ;;
|
|
esac
|
|
) < "$output_quota_fifo" &
|
|
drain_pid=$!
|
|
fi
|
|
|
|
if [ "$launch_mode" = "argv" ]; then
|
|
if [ -n "$output_quota_fifo" ]; then
|
|
"$@" > "$output_quota_fifo" 2>&1 &
|
|
else
|
|
"$@" &
|
|
fi
|
|
else
|
|
if [ -n "$output_quota_fifo" ]; then
|
|
"$launch_shell" -c "$launch_shell_command" > "$output_quota_fifo" 2>&1 &
|
|
else
|
|
"$launch_shell" -c "$launch_shell_command" &
|
|
fi
|
|
fi
|
|
child_pid=$!
|
|
|
|
forward_term() {
|
|
kill -TERM "$child_pid" 2>/dev/null || :
|
|
}
|
|
forward_int() {
|
|
kill -INT "$child_pid" 2>/dev/null || :
|
|
}
|
|
forward_hup() {
|
|
kill -HUP "$child_pid" 2>/dev/null || :
|
|
}
|
|
trap forward_term TERM
|
|
trap forward_int INT
|
|
trap forward_hup HUP
|
|
|
|
# A trapped signal may interrupt wait before the child has actually exited.
|
|
# Keep the group leader alive so LocalProcessExecutor cannot mistake a living
|
|
# descendant for a fully closed process group.
|
|
while :; do
|
|
wait "$child_pid"
|
|
exit_code=$?
|
|
if ! kill -0 "$child_pid" 2>/dev/null; then
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "$drain_pid" ]; then
|
|
wait "$drain_pid" 2>/dev/null || :
|
|
rm -f "$output_quota_fifo" 2>/dev/null || :
|
|
fi
|
|
|
|
finished_at_ms=$(( $(date +%s) * 1000 ))
|
|
if [ "$finished_at_ms" -lt "$started_at_ms" ]; then
|
|
finished_at_ms=$started_at_ms
|
|
fi
|
|
|
|
receipt_payload="{\"schemaVersion\":1,\"runId\":\"$run_id\",\"attemptId\":\"$attempt_id\",\"callbackSequence\":$callback_sequence,\"token\":\"$callback_token\",\"startedAtMs\":$started_at_ms,\"finishedAtMs\":$finished_at_ms,\"exitCode\":$exit_code}"
|
|
|
|
# noclobber protects the random temporary name; hard-link publication protects
|
|
# an immutable final receipt from replacement. Publication failure never
|
|
# changes the user's exit code: the live channel can still complete, while a
|
|
# restarted control plane will conservatively treat a missing receipt as lost.
|
|
if (set -C; printf '%s' "$receipt_payload" > "$receipt_temporary") 2>/dev/null; then
|
|
sync -f "$receipt_temporary" 2>/dev/null || :
|
|
if ln "$receipt_temporary" "$receipt_target" 2>/dev/null; then
|
|
sync -f "$receipt_target" 2>/dev/null || :
|
|
fi
|
|
rm -f "$receipt_temporary" 2>/dev/null || :
|
|
sync -f "${receipt_target%/*}" 2>/dev/null || :
|
|
fi
|
|
|
|
exit "$exit_code"
|