Fix wasm compile source race
This commit is contained in:
parent
36ea0cd2a5
commit
096138d6a1
@ -365,7 +365,10 @@ header free-functions are `inline`. The wasm backend exposes only declarations
|
||||
its permissions and proves the next CLI request compiles it, then sends 48
|
||||
requests and asserts the observed worker PID set does not exceed
|
||||
`WORKER_COUNT`, guarding against accidental reintroduction of request-count
|
||||
recycling.
|
||||
recycling. It also races a source edit against an active unit compile after
|
||||
the generated C++ snapshot has been written. The compiler must either retry
|
||||
and serve the post-edit source or fail closed; it must never stamp current
|
||||
source metadata onto wasm produced from an older snapshot.
|
||||
`scripts/test_cold_component_deadline.sh` separately compiles a deliberately
|
||||
cold component that exceeds the development epoch window and proves the
|
||||
parent request still renders it. The dependency-invalidation gate also holds
|
||||
|
||||
@ -15,6 +15,9 @@ mutation_file="/tmp/uce-dependency-mutation-$$"
|
||||
post_body="/tmp/uce-dependency-post-body-$$"
|
||||
post_headers="/tmp/uce-dependency-post-headers-$$"
|
||||
lock_ready_file="/tmp/uce-dependency-lock-ready-$$"
|
||||
race_output="/tmp/uce-source-race-output-$$"
|
||||
race_error="/tmp/uce-source-race-error-$$"
|
||||
race_status="/tmp/uce-source-race-status-$$"
|
||||
http_host="${UCE_TEST_HTTP_HOST:-uce.openfu.com}"
|
||||
|
||||
cleanup() {
|
||||
@ -22,7 +25,7 @@ cleanup() {
|
||||
if [[ -n "$cache_dir" ]]; then
|
||||
rm -rf "$cache_dir"
|
||||
fi
|
||||
rm -f "$mutation_file" "$post_body" "$post_headers" "$lock_ready_file"
|
||||
rm -f "$mutation_file" "$post_body" "$post_headers" "$lock_ready_file" "$race_output" "$race_error" "$race_status"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
mkdir -p "$source_dir"
|
||||
@ -179,6 +182,56 @@ touch -d "@$parent_mtime" "$parent_wasm"
|
||||
rm -f "$cache_dir/parent.uce.cwasm"
|
||||
for _ in {1..16}; do assert_marker parent dependency-marker-c; done
|
||||
|
||||
race_unit="$source_dir/source-race.uce"
|
||||
race_cpp="$cache_dir/source-race.uce.cpp"
|
||||
{
|
||||
printf '%s\n' 'String source_race_marker() { return("source-race-marker-a"); }'
|
||||
for i in $(seq 1 3500); do
|
||||
printf 'int source_race_padding_%s() { return(%s); }\n' "$i" "$i"
|
||||
done
|
||||
printf '%s\n' 'CLI(Request& context) { print(source_race_marker()); }'
|
||||
} >"$race_unit"
|
||||
rm -f "$cache_dir/source-race.uce.cpp" "$cache_dir/source-race.uce.wasm" "$cache_dir/source-race.uce.cwasm" "$cache_dir/source-race.uce.meta.txt"
|
||||
(
|
||||
set +e
|
||||
scripts/uce-cli "/$test_name/source-race.uce" >"$race_output" 2>"$race_error"
|
||||
echo "$?" >"$race_status"
|
||||
) &
|
||||
race_pid=$!
|
||||
deadline=$((SECONDS + 10))
|
||||
while [[ ! -e "$race_cpp" && $SECONDS -lt $deadline ]]; do
|
||||
if ! kill -0 "$race_pid" 2>/dev/null; then
|
||||
echo "source-race compile finished before publishing generated C++" >&2
|
||||
cat "$race_output" "$race_error" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.02
|
||||
done
|
||||
if [[ ! -e "$race_cpp" ]]; then
|
||||
echo "source-race compile did not publish generated C++ before deadline" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -q 'source-race-marker-a' "$race_cpp"; then
|
||||
echo "source-race generated C++ did not contain the initial marker" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! kill -0 "$race_pid" 2>/dev/null; then
|
||||
echo "source-race compile finished before source mutation hook" >&2
|
||||
cat "$race_output" "$race_error" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
sed -i 's/source-race-marker-a/source-race-marker-b/' "$race_unit"
|
||||
wait "$race_pid"
|
||||
if [[ "$(cat "$race_status" 2>/dev/null || echo 1)" != "0" ]]; then
|
||||
echo "source-race CLI request failed" >&2
|
||||
cat "$race_output" "$race_error" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$(cat "$race_output")" != *"source-race-marker-b"* ]]; then
|
||||
echo "source changed during compile but UCE served stale wasm: $(cat "$race_output")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
worker_count=$(awk -F= '/^[[:space:]]*WORKER_COUNT[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg 2>/dev/null || true)
|
||||
worker_count="${worker_count:-4}"
|
||||
worker_pids=""
|
||||
|
||||
@ -215,16 +215,31 @@ String compiler_unit_build_token()
|
||||
);
|
||||
}
|
||||
|
||||
String compiler_unit_metadata_text(Request* context, SharedUnit* su)
|
||||
String compiler_unit_metadata_text(Request* context, SharedUnit* su, String input_signature = "")
|
||||
{
|
||||
if(input_signature == "")
|
||||
input_signature = compiler_unit_input_signature(context, su);
|
||||
return(
|
||||
"format=uce-unit-metadata-v1\n"
|
||||
"unit_abi_version=" + std::to_string(UCE_UNIT_ABI_VERSION) + "\n"
|
||||
"input_signature=" + compiler_unit_input_signature(context, su) + "\n"
|
||||
"input_signature=" + input_signature + "\n"
|
||||
"build_token=" + compiler_unit_build_token() + "\n"
|
||||
);
|
||||
}
|
||||
|
||||
String compiler_cached_wasm_path(String wasm_path)
|
||||
{
|
||||
if(wasm_path.size() >= 5 && wasm_path.rfind(".wasm", wasm_path.size() - 5) == wasm_path.size() - 5)
|
||||
return(wasm_path.substr(0, wasm_path.size() - 5) + ".cwasm");
|
||||
return(wasm_path + ".cwasm");
|
||||
}
|
||||
|
||||
void compiler_unlink_unit_wasm_artifacts(SharedUnit* su)
|
||||
{
|
||||
file_unlink(su->wasm_name);
|
||||
file_unlink(compiler_cached_wasm_path(su->wasm_name));
|
||||
}
|
||||
|
||||
String compiler_wasm_compile_script(Request* context)
|
||||
{
|
||||
String script = "scripts/compile_wasm_unit";
|
||||
@ -832,33 +847,48 @@ void compile_shared_unit(Request* context, SharedUnit* su)
|
||||
}
|
||||
|
||||
shell_exec("mkdir -p " + shell_escape(su->pre_path));
|
||||
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(context, su));
|
||||
file_put_contents(su->api_file_name, join(su->api_declarations, "\n"));
|
||||
String compiled_input_signature;
|
||||
for(u64 attempt = 0; attempt < 2; attempt++)
|
||||
{
|
||||
su->api_declarations.clear();
|
||||
compiled_input_signature = compiler_unit_input_signature(context, su);
|
||||
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(context, su));
|
||||
file_put_contents(su->api_file_name, join(su->api_declarations, "\n"));
|
||||
|
||||
su->compiler_messages = trim(shell_exec(shell_escape(compiler_wasm_compile_script(context))+" "+
|
||||
shell_escape(su->src_path)+" "+
|
||||
shell_escape(su->bin_path)+" "+
|
||||
shell_escape(su->file_name)+" "+
|
||||
shell_escape(su->pre_file_name)+" "+
|
||||
shell_escape(su->wasm_file_name)
|
||||
));
|
||||
su->compiler_messages = trim(shell_exec(shell_escape(compiler_wasm_compile_script(context))+" "+
|
||||
shell_escape(su->src_path)+" "+
|
||||
shell_escape(su->bin_path)+" "+
|
||||
shell_escape(su->file_name)+" "+
|
||||
shell_escape(su->pre_file_name)+" "+
|
||||
shell_escape(su->wasm_file_name)
|
||||
));
|
||||
|
||||
if(su->compiler_messages.length() == 0 && !file_exists(su->wasm_name))
|
||||
su->compiler_messages = "wasm compile script completed without creating " + su->wasm_name;
|
||||
if(su->compiler_messages.length() == 0 && !file_exists(su->wasm_name))
|
||||
su->compiler_messages = "wasm compile script completed without creating " + su->wasm_name;
|
||||
if(su->compiler_messages.length() > 0)
|
||||
break;
|
||||
String current_input_signature = compiler_unit_input_signature(context, su);
|
||||
if(current_input_signature == compiled_input_signature)
|
||||
break;
|
||||
compiler_unlink_unit_wasm_artifacts(su);
|
||||
if(attempt == 1)
|
||||
su->compiler_messages = "source changed during wasm compile; retry required";
|
||||
}
|
||||
|
||||
if(su->compiler_messages.length() > 0)
|
||||
{
|
||||
String raw_messages = su->compiler_messages;
|
||||
file_put_contents(su->compile_output_file_name, raw_messages + "\n");
|
||||
file_put_contents(su->wasm_check_file_name, raw_messages + "\n");
|
||||
file_unlink(su->wasm_name);
|
||||
compiler_unlink_unit_wasm_artifacts(su);
|
||||
compiler_record_compile_result(su, time_precise() - comp_start, false, "compile_error", raw_messages);
|
||||
printf("%s \n", compiler_format_compile_failure(su, raw_messages).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
su->last_compiled = file_mtime(su->wasm_name);
|
||||
file_put_contents(su->meta_file_name, compiler_unit_metadata_text(context, su));
|
||||
file_unlink(compiler_cached_wasm_path(su->wasm_name));
|
||||
file_put_contents(su->meta_file_name, compiler_unit_metadata_text(context, su, compiled_input_signature));
|
||||
file_unlink(su->compile_output_file_name);
|
||||
file_unlink(su->wasm_check_file_name);
|
||||
compiler_record_compile_result(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user