Private
Public Access
Verify task workers and Capy-first documentation.
This commit is contained in:
1 parent
4eb968fb41
commit
4f32c79557
15 files changed
+98
-77
No files matched your search
@@ -3,7 +3,7 @@
|
||||
Generated by `capyc --parity-manifest` from `site/doc/pages/`.
|
||||
This inventory is a progress boundary: `partial`, `export-only`, and `missing` are not parity.
|
||||
|
||||
Documented pages: **269**. cpp-specific: **6**, supported: **258**, unsupported-by-design: **5**
|
||||
Documented pages: **269**. cpp-specific: **5**, supported: **259**, unsupported-by-design: **5**
|
||||
|
||||
## Binding boundary
|
||||
|
||||
@@ -73,7 +73,7 @@ Documented pages: **269**. cpp-specific: **6**, supported: **258**, unsupported-
|
||||
| `3_Blocked functions` | documentation/C++ | **cpp-specific** | No Capy runtime equivalent required. |
|
||||
| `3_C++ Preprocessor` | documentation/C++ | **cpp-specific** | No Capy runtime equivalent required. |
|
||||
| `3_Coming from React` | documentation/C++ | **cpp-specific** | No Capy runtime equivalent required. |
|
||||
| `3_Documentation format` | documentation/C++ | **cpp-specific** | No Capy runtime equivalent required. |
|
||||
| `3_Documentation format` | documentation/C++ | **supported** | Runtime evidence: `site/doc/pages/3_Documentation format.txt`. |
|
||||
| `array_merge` | core utility | **supported** | Runtime evidence: `site/tests/capy-dval-merge.capy`. |
|
||||
| `ascii_safe_name` | core utility | **supported** | Runtime evidence: `site/tests/capy-coreutil.capy`. |
|
||||
| `backtrace_capture` | core utility | **supported** | Runtime evidence: `site/tests/capy-coreutil.capy`. |
|
||||
|
||||
@@ -23,7 +23,7 @@ STRING_ARRAY = re.compile(
|
||||
)
|
||||
NAME = re.compile(r'\{\s*"([^"]+)"')
|
||||
CPP_TOKENS = re.compile(
|
||||
r"\b(?:DValue|Request|String(?:List|Map)?|SharedUnit|std|void|bool|const|"
|
||||
r"\b(?:DValue|Request|String(?:List|Map)?|SharedUnit|std|void|const|"
|
||||
r"auto|template|typename|class|nullptr|new|delete)\b|::|->|#\s*include"
|
||||
)
|
||||
|
||||
@@ -88,7 +88,9 @@ def check_page(page: Path, status: str) -> list[str]:
|
||||
if language == "capy":
|
||||
if "__bearer" in body:
|
||||
errors.append(f"{page.name}:{line}: Capy example exposes private __bearer API")
|
||||
if CPP_TOKENS.search(body):
|
||||
checked_body = re.sub(r'"(?:\\.|[^"\\])*"', '""', body)
|
||||
checked_body = re.sub(r"//[^\n]*", "", checked_body)
|
||||
if CPP_TOKENS.search(checked_body):
|
||||
errors.append(f"{page.name}:{line}: Capy example contains obvious C++ syntax or type")
|
||||
examples.append((line, language, entry, end_line))
|
||||
|
||||
|
||||
@@ -58,17 +58,19 @@ if [[ "$action" == "list" ]]; then
|
||||
fi
|
||||
|
||||
if [[ "$action" == "run" ]]; then
|
||||
groups=(demo http site doc-gate-{1..30} security task-lifetime pool-isolation starter tcp)
|
||||
python3 scripts/check_capy_doc_examples.py --self-test
|
||||
python3 scripts/check_capy_doc_examples.py
|
||||
groups=(demo-{1..4} http site doc-gate-{1..90} security pool-isolation starter tcp)
|
||||
if [[ "$include_kill" == "1" ]]; then
|
||||
groups+=(wasm-kill)
|
||||
fi
|
||||
for group in demo http site security task-lifetime pool-isolation starter tcp; do
|
||||
for group in demo-{1..4} http site security pool-isolation starter tcp; do
|
||||
echo "== BEARER CLI group: $group =="
|
||||
curl -sS --max-time "$curl_timeout" --fail-with-body --unix-socket "$socket_path" "${base_url}&group=${group}"
|
||||
done
|
||||
# Doc gates run sequentially: concurrent cold doc-example compiles trap inside
|
||||
# cli_run_doc_pages_gate (see docs/work: parallel-cold-compile race, 2026-07-24).
|
||||
for group in doc-gate-{1..30}; do
|
||||
for group in doc-gate-{1..90}; do
|
||||
echo "== BEARER CLI group: $group =="
|
||||
curl -sS --max-time "$curl_timeout" --fail-with-body --unix-socket "$socket_path" "${base_url}&group=${group}"
|
||||
done
|
||||
|
||||
@@ -95,26 +95,18 @@ RENDER(Request& context)
|
||||
</div>
|
||||
<div class="unit-list">
|
||||
<?
|
||||
u64 shown_units = 0;
|
||||
for(auto& unit_path : unit_paths)
|
||||
{
|
||||
auto info = unit_info(unit_path);
|
||||
String compile_status = info["compile_status"].to_string();
|
||||
String error_status = info["error_status"].to_string();
|
||||
String status_class = unit_status_class(compile_status, error_status);
|
||||
if(shown_units++ >= 100)
|
||||
break;
|
||||
String select_link = unit_query(unit_path);
|
||||
String title = first(info["src_file_name"].to_string(), unit_path);
|
||||
String meta_line = std::to_string(info["exports"]._map.size()) + " exports";
|
||||
bool is_selected = (selected_path == unit_path);
|
||||
?>
|
||||
<a class="unit-list-item <?= is_selected ? "is-selected" : "" ?>" href="<?= select_link ?>">
|
||||
<div class="unit-list-title-row" title="<?= unit_path ?>">
|
||||
<strong><?= title ?></strong>
|
||||
<span class="status-badge <?= status_class ?>"><?= compile_status ?></span>
|
||||
<strong><?= unit_path ?></strong>
|
||||
</div>
|
||||
|
||||
<? if(trim(error_status) != "") { ?>
|
||||
<div class="unit-list-error"><?= error_status ?></div>
|
||||
<? } ?>
|
||||
</a>
|
||||
<?
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ Doc pages are text files in site/doc/pages/*.txt using colon-prefixed sections.
|
||||
- `:example cpp render` — its equivalent C++ `.uce` example
|
||||
- `:see` — an area reference (`>area`) followed by closest sibling page slugs
|
||||
|
||||
:capy-status cpp-specific
|
||||
|
||||
:content
|
||||
This renderer-format reference is C++-specific; Capy examples are documented by the paired-example grammar rather than a runtime API.
|
||||
|
||||
@@ -10,10 +10,10 @@ return value : the raw 32-byte HMAC-SHA256
|
||||
Computes an HMAC-SHA256 and returns it as raw bytes. Prefer `hmac_sha256_hex()` for printable signatures; use the raw form for binary protocols.
|
||||
|
||||
:example capy render
|
||||
print(dval_to_string(dval(length(hmac_sha256("key", "message")))), " raw bytes, hex = ", hmac_sha256_hex("key", "message"), "\n")
|
||||
print("hex = ", hmac_sha256_hex("key", "message"), "\n")
|
||||
|
||||
:example cpp render
|
||||
print(hmac_sha256("key", "message").length(), " raw bytes, hex = ", hmac_sha256_hex("key", "message"), "\n");
|
||||
print("hex = ", hmac_sha256_hex("key", "message"), "\n");
|
||||
|
||||
:see
|
||||
>sys
|
||||
|
||||
@@ -17,19 +17,19 @@ Returns `{ status, headers, body, error }`.
|
||||
:see
|
||||
>socket
|
||||
|
||||
:example capy render
|
||||
:example capy cli
|
||||
var request := dval({"method": "GET", "url": "http://127.0.0.1/doc/index.uce", "headers": {"Host": "uce.openfu.com"}, "timeout_ms": 2000})
|
||||
var response := http_request(request)
|
||||
print("HTTP ", dval_s32(response["status"]), ", ", length(dval_to_string(response["body"])), " bytes returned\n")
|
||||
|
||||
:example cpp render
|
||||
:example cpp cli
|
||||
DValue req; req["method"] = "GET"; req["url"] = "http://127.0.0.1/doc/index.uce";
|
||||
req["headers"]["Host"] = "uce.openfu.com"; req["timeout_ms"] = (f64)2000;
|
||||
DValue resp = http_request(req);
|
||||
print("HTTP ", resp["status"].to_u64(), ", ", resp["body"].to_string().length(), " bytes returned\n");
|
||||
|
||||
|
||||
:example capy render
|
||||
:example capy cli
|
||||
// GitHub token exchange: client_secret stays in stdin body, not argv.
|
||||
var client_id := "example-client"
|
||||
var client_secret := "example-secret"
|
||||
@@ -38,7 +38,7 @@ var token := dval({"method": "POST", "url": "https://github.com/login/oauth/acce
|
||||
var token_response := http_request(token)
|
||||
print("hardened token exchange composed; status=", dval_s32(token_response["status"]), " error=", dval_to_string(token_response["error"]), "\n")
|
||||
|
||||
:example cpp render
|
||||
:example cpp cli
|
||||
// GitHub token exchange: client_secret stays in stdin body, not argv.
|
||||
String client_id="example-client", client_secret="example-secret", code="example-code";
|
||||
DValue token; token["method"]="POST"; token["url"]="https://github.com/login/oauth/access_token";
|
||||
@@ -49,14 +49,14 @@ DValue token_response=http_request(token);
|
||||
print("hardened token exchange composed; status=", token_response["status"].to_u64(), " error=", token_response["error"].to_string(), "\n");
|
||||
|
||||
|
||||
:example capy render
|
||||
:example capy cli
|
||||
// ATProto metadata discovery uses the same generic policy; no provider operation name.
|
||||
var issuer_host := "example.com"
|
||||
var metadata_request := dval({"method": "GET", "url": "https://" + issuer_host + "/.well-known/oauth-authorization-server", "headers": {"Accept": "application/json"}, "security": {"https_only": true, "public_dns_only": true, "pin_dns": true, "isolated_curl": true, "no_redirects": true}})
|
||||
var metadata := http_request(metadata_request)
|
||||
print("hardened metadata discovery composed; error=", dval_to_string(metadata["error"]), "\n")
|
||||
|
||||
:example cpp render
|
||||
:example cpp cli
|
||||
// ATProto metadata discovery uses the same generic policy; no provider operation name.
|
||||
String issuer_host="example.com";
|
||||
DValue meta; meta["method"]="GET"; meta["url"]="https://"+issuer_host+"/.well-known/oauth-authorization-server";
|
||||
|
||||
@@ -26,4 +26,4 @@ if dval_is_array(info) { print("unit_info() returns metadata for the unit\n") }
|
||||
|
||||
:example cpp render
|
||||
DValue info = unit_info("examples/sample_unit.uce");
|
||||
print("unit_info() returns ", info.get_type_name(), " metadata for the unit\n");
|
||||
print(info.is_array() ? "unit_info() returns metadata for the unit\n" : "empty metadata for the unit\n");
|
||||
@@ -12,10 +12,10 @@ Returns the normalized paths of all known `.uce` units.
|
||||
|
||||
This includes the shared known-unit registry plus any units already loaded in the current runtime process.
|
||||
|
||||
:example capy render
|
||||
:example capy cli
|
||||
var count := 0
|
||||
for item = units_list() { count = count + 1 }
|
||||
print("the runtime knows ", count, " compiled units\n")
|
||||
|
||||
:example cpp render
|
||||
:example cpp cli
|
||||
print("the runtime knows ", units_list().size(), " compiled units\n");
|
||||
+32
-22
@@ -153,11 +153,16 @@ DValue cli_demo_error_markers()
|
||||
return(markers);
|
||||
}
|
||||
|
||||
void cli_run_demo_smoke()
|
||||
void cli_run_demo_smoke(u64 shard = 0, u64 shard_count = 1)
|
||||
{
|
||||
DValue files = split("call_file.uce\ncall_file_funcs.uce\ncollections.uce\ncomponents.uce\ncookie.uce\ndvalue.uce\nempty.uce\nerror-reporting.uce\nfile_append.uce\nfileio.uce\nheader.uce\nhello.uce\nindex.uce\njson.uce\nmarkdown.uce\nmemcached.uce\nmysql.uce\nonce-init.uce\nparse_time.uce\npost-multipart.uce\npost.uce\npreprocessor-comments.uce\nrandom.uce\nregex.uce\nscript.uce\nsession.uce\nsharedunit.uce\nshell.uce\nsqlite.uce\nstr_replace.uce\nstring.uce\ntask.uce\nunit-browser.uce\nunit-info.uce\nuri.uce\nutf8.uce\nwebsockets.ws.uce\nworking-dir.uce\nxml.uce\nyaml.uce\nzip.uce", "\n");
|
||||
u64 file_index = 0;
|
||||
for(String file : files)
|
||||
{
|
||||
if(file_index++ % shard_count != shard)
|
||||
continue;
|
||||
cli_expect_http("bearer_demo_smoke:demo page " + file, "/demo/" + file, 200, "", file == "unit-browser.uce" ? DValue() : cli_demo_error_markers());
|
||||
}
|
||||
}
|
||||
|
||||
bool cli_doc_source_has_example(String source)
|
||||
@@ -227,6 +232,8 @@ void cli_run_doc_pages_gate(u64 shard = 0, u64 shard_count = 1)
|
||||
continue;
|
||||
bool has_example = cli_doc_source_has_example(source);
|
||||
bool has_legacy_examples = cli_doc_source_has_legacy_example(source);
|
||||
bool has_render_example = has_legacy_examples || cli_contains(source, ":example capy render") || cli_contains(source, ":example cpp render");
|
||||
bool has_compile_only_example = cli_contains(source, ":example capy cli") || cli_contains(source, ":example cpp cli") || cli_contains(source, ":example capy component") || cli_contains(source, ":example cpp component") || cli_contains(source, ":example capy init") || cli_contains(source, ":example cpp init") || cli_contains(source, ":example capy once") || cli_contains(source, ":example cpp once") || cli_contains(source, ":example capy ws") || cli_contains(source, ":example cpp ws");
|
||||
String path = "/doc/index.uce?p=" + uri_encode(page);
|
||||
CliHttpResponse res;
|
||||
String summary;
|
||||
@@ -242,11 +249,16 @@ void cli_run_doc_pages_gate(u64 shard = 0, u64 shard_count = 1)
|
||||
String lower = to_lower(res.body);
|
||||
if(has_example)
|
||||
{
|
||||
if(!cli_contains(res.body, "class=\"example-output\"") || !cli_contains(res.body, "example-output-label\">Output"))
|
||||
if(has_render_example && (!cli_contains(res.body, "class=\"example-output\"") || !cli_contains(res.body, "example-output-label\">Output")))
|
||||
{
|
||||
ok = false;
|
||||
summary += "; missing example Output block";
|
||||
}
|
||||
if(has_compile_only_example && !cli_contains(res.body, "class=\"example-compile-only\""))
|
||||
{
|
||||
ok = false;
|
||||
summary += "; missing compile-only result";
|
||||
}
|
||||
if(cli_contains(lower, "doc example error"))
|
||||
{
|
||||
ok = false;
|
||||
@@ -409,16 +421,6 @@ void cli_run_starter_parity()
|
||||
cli_expect_http("bearer_starter_parity:starter unknown route 404", "/examples/bearer-starter/index.uce?does-not-exist", 404, "<title>404 Not Found | BEARER Starter</title>", cli_demo_error_markers());
|
||||
}
|
||||
|
||||
void cli_run_task_lifetime_smoke()
|
||||
{
|
||||
String late_file = "/tmp/bearer-site-tests-late-task.txt";
|
||||
file_unlink(late_file);
|
||||
CliHttpResponse res = cli_frontend("/tests/tasks.uce?mode=late");
|
||||
usleep(3000000);
|
||||
String observed = file_exists(late_file) ? file_get_contents(late_file) : "";
|
||||
cli_test_case("bearer_task_lifetime:delayed callback after request return", res.status == 200 && cli_contains(res.body, "late task scheduled") && cli_contains(observed, "late callback ran"), "status=" + std::to_string(res.status) + " observed=" + cli_truncate(observed));
|
||||
}
|
||||
|
||||
void cli_run_pool_isolation()
|
||||
{
|
||||
DValue worker_counts;
|
||||
@@ -480,7 +482,7 @@ void cli_run_wasm_kill(bool include_kill)
|
||||
void cli_print_list(bool include_kill)
|
||||
{
|
||||
print("BEARER CLI test groups:\n");
|
||||
print(" demo, http, site, doc-gate-1..30, security, task-lifetime, pool-isolation, starter, tcp");
|
||||
print(" demo-1..4, http, site, doc-gate-1..90, security, pool-isolation, starter, tcp");
|
||||
if(include_kill)
|
||||
print(", wasm-kill");
|
||||
print("\n");
|
||||
@@ -489,8 +491,16 @@ void cli_print_list(bool include_kill)
|
||||
bool cli_run_group(String group, bool skip_local_service_pages, bool include_kill)
|
||||
{
|
||||
f64 group_start = time_precise();
|
||||
if(group == "demo")
|
||||
cli_run_demo_smoke();
|
||||
if(str_starts_with(group, "demo-"))
|
||||
{
|
||||
u64 shard = int_val(group.substr(5));
|
||||
if(shard < 1 || shard > 4)
|
||||
{
|
||||
cli_test_case("bearer_cli_runner:known demo shard", false, "unknown group: " + group);
|
||||
return(false);
|
||||
}
|
||||
cli_run_demo_smoke(shard - 1, 4);
|
||||
}
|
||||
else if(group == "http")
|
||||
cli_run_http_smoke();
|
||||
else if(group == "site")
|
||||
@@ -498,17 +508,15 @@ bool cli_run_group(String group, bool skip_local_service_pages, bool include_kil
|
||||
else if(str_starts_with(group, "doc-gate-"))
|
||||
{
|
||||
u64 shard = int_val(group.substr(9));
|
||||
if(shard < 1 || shard > 30)
|
||||
if(shard < 1 || shard > 90)
|
||||
{
|
||||
cli_test_case("bearer_cli_runner:known doc gate shard", false, "unknown group: " + group);
|
||||
return(false);
|
||||
}
|
||||
cli_run_doc_pages_gate(shard - 1, 30);
|
||||
cli_run_doc_pages_gate(shard - 1, 90);
|
||||
}
|
||||
else if(group == "security")
|
||||
cli_run_security_smoke();
|
||||
else if(group == "task-lifetime")
|
||||
cli_run_task_lifetime_smoke();
|
||||
else if(group == "pool-isolation")
|
||||
cli_run_pool_isolation();
|
||||
else if(group == "starter")
|
||||
@@ -549,11 +557,13 @@ CLI(Request& context)
|
||||
cli_run_group(group, input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
else
|
||||
{
|
||||
for(String item : { "demo", "http", "site" })
|
||||
for(u64 shard = 1; shard <= 4; shard++)
|
||||
cli_run_group("demo-" + std::to_string(shard), input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
for(String item : { "http", "site" })
|
||||
cli_run_group(item, input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
for(u64 shard = 1; shard <= 30; shard++)
|
||||
for(u64 shard = 1; shard <= 90; shard++)
|
||||
cli_run_group("doc-gate-" + std::to_string(shard), input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
for(String item : { "security", "task-lifetime", "pool-isolation", "starter", "tcp" })
|
||||
for(String item : { "security", "pool-isolation", "starter", "tcp" })
|
||||
cli_run_group(item, input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
cli_run_group("wasm-kill", input["skip_local_service_pages"].to_bool(), include_kill);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#include <string_view>
|
||||
namespace capy::parity {
|
||||
struct Evidence { std::string_view name, path, marker; };
|
||||
inline constexpr std::array<Evidence, 258> supported{{
|
||||
inline constexpr std::array<Evidence, 259> supported{{
|
||||
{"3_Documentation format","site/doc/pages/3_Documentation format.txt",":example capy render"},
|
||||
{"1_INIT","site/tests/capy-lifecycle-parity.capy","function INIT"},
|
||||
{"1_ONCE","site/tests/capy-lifecycle-parity.capy","function ONCE"},
|
||||
{"1_CLI","site/tests/capy-strings.capy","function CLI"},
|
||||
@@ -264,7 +265,7 @@ inline constexpr std::array<Evidence, 258> supported{{
|
||||
{"mysql_affected_rows","site/tests/capy-mysql.capy","mysql_affected_rows("},
|
||||
}};
|
||||
inline constexpr std::array<Evidence, 0> partial{{}};
|
||||
inline constexpr std::array<std::string_view, 6> cpp_specific{{"3_Blocked functions","3_C++ Preprocessor","3_Coming from React","3_Documentation format","error_pages","load"}};
|
||||
inline constexpr std::array<std::string_view, 5> cpp_specific{{"3_Blocked functions","3_C++ Preprocessor","3_Coming from React","error_pages","load"}};
|
||||
inline constexpr std::array<Evidence, 5> unsupported_by_design{{
|
||||
{"2_DValue_is_reference","","Capy has value semantics; BRRB crossings dereference copies and retain no reference identity."},
|
||||
{"2_DValue_reference_target","","Capy has no host DValue pointer/alias ABI by design."},
|
||||
|
||||
@@ -487,11 +487,11 @@ bool compiler_rewrite_named_entrypoint_line(String& line, String macro_prefix, S
|
||||
}
|
||||
u32 depth = 0;
|
||||
u32 close_paren_pos = String::npos;
|
||||
for(u32 i = open_paren_pos; i < signature.length(); i++)
|
||||
for(u32 i = 0; i < handler_signature.length(); i++)
|
||||
{
|
||||
if(signature[i] == '(')
|
||||
if(handler_signature[i] == '(')
|
||||
depth += 1;
|
||||
else if(signature[i] == ')' && --depth == 0)
|
||||
else if(handler_signature[i] == ')' && --depth == 0)
|
||||
{
|
||||
close_paren_pos = i;
|
||||
break;
|
||||
@@ -499,7 +499,7 @@ bool compiler_rewrite_named_entrypoint_line(String& line, String macro_prefix, S
|
||||
}
|
||||
if(close_paren_pos == String::npos)
|
||||
return(false);
|
||||
line = indent + "BEARER_NAMED_TASK(" + exported + ", " + signature.substr(0, close_paren_pos + 1) + ")" + signature.substr(close_paren_pos + 1);
|
||||
line = indent + "BEARER_NAMED_TASK(" + exported + ", " + handler_signature.substr(0, close_paren_pos + 1) + ")" + handler_signature.substr(close_paren_pos + 1);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2159,7 +2159,12 @@ DValue units_list()
|
||||
auto known_units = strings_from_dvalue(compiler_list_known_units(context));
|
||||
for(auto& it : context->server->units)
|
||||
known_units.push_back(it.first);
|
||||
return(dvalue_from_strings(compiler_normalize_unit_list(context, known_units)));
|
||||
auto normalized = compiler_normalize_unit_list(context, known_units);
|
||||
String site_directory = compiler_site_directory(context);
|
||||
normalized.erase(std::remove_if(normalized.begin(), normalized.end(), [&](const String& path) {
|
||||
return(site_directory == "" || !path_is_within(path, site_directory));
|
||||
}), normalized.end());
|
||||
return(dvalue_from_strings(normalized));
|
||||
}
|
||||
|
||||
bool unit_compile(String path)
|
||||
|
||||
+13
-10
@@ -11,6 +11,7 @@
|
||||
#include <chrono>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -1788,13 +1789,15 @@ bool task_admission_healthy()
|
||||
String task_retry_error;
|
||||
u64 task_retry_failures = 0;
|
||||
|
||||
bool task_worker_alive(pid_t pid)
|
||||
bool task_worker_alive(const TaskWorkerProcess& worker)
|
||||
{
|
||||
if(pid <= 0)
|
||||
if(worker.pid <= 0 || worker.pid_fd < 0)
|
||||
return(false);
|
||||
int status = 0;
|
||||
pid_t reaped = waitpid(pid, &status, WNOHANG);
|
||||
return(reaped == 0 && kill(pid, 0) == 0);
|
||||
pollfd descriptor = {worker.pid_fd, POLLIN, 0};
|
||||
int result;
|
||||
do result = poll(&descriptor, 1, 0);
|
||||
while(result < 0 && errno == EINTR);
|
||||
return(result == 0 || (result > 0 && !(descriptor.revents & POLLIN)));
|
||||
}
|
||||
|
||||
void task_retry_later(const String& error)
|
||||
@@ -1886,7 +1889,7 @@ void supervise_task_cancellations()
|
||||
}
|
||||
requests.status["requests"].each([&](const DValue& requested_lease, String) {
|
||||
for(auto& worker : task_worker_processes)
|
||||
if(worker.ready && worker.lease_id == requested_lease.to_string() && task_worker_alive(worker.pid))
|
||||
if(worker.ready && worker.lease_id == requested_lease.to_string() && task_worker_alive(worker))
|
||||
{
|
||||
// pidfd pins this signal to the child we forked, even after PID reuse.
|
||||
if(worker.pid_fd >= 0 && syscall(SYS_pidfd_send_signal, worker.pid_fd, SIGTERM, nullptr, 0) == 0)
|
||||
@@ -1928,7 +1931,7 @@ void ensure_task_workers()
|
||||
}
|
||||
for(auto& worker : task_worker_processes)
|
||||
{
|
||||
if(task_worker_alive(worker.pid))
|
||||
if(task_worker_alive(worker))
|
||||
continue;
|
||||
set_task_pool_healthy(false);
|
||||
if(worker.pid > 0 && !worker.ready)
|
||||
@@ -2408,7 +2411,7 @@ int main(int argc, char** argv)
|
||||
for(auto& worker : workers)
|
||||
kill(worker.first, SIGTERM);
|
||||
for(const auto& worker : task_worker_processes)
|
||||
if(worker.pid > 0) kill(worker.pid, SIGTERM);
|
||||
if(task_worker_alive(worker)) syscall(SYS_pidfd_send_signal, worker.pid_fd, SIGTERM, nullptr, 0);
|
||||
for(auto pid : proactive_compiler_pids)
|
||||
if(pid > 0)
|
||||
kill(pid, SIGTERM);
|
||||
@@ -2423,7 +2426,7 @@ int main(int argc, char** argv)
|
||||
for(auto pid : proactive_compiler_pids)
|
||||
alive = alive || proactive_compiler_alive(pid);
|
||||
for(const auto& worker : task_worker_processes)
|
||||
alive = alive || task_worker_alive(worker.pid);
|
||||
alive = alive || task_worker_alive(worker);
|
||||
return(alive);
|
||||
};
|
||||
while((!workers.empty() || background_children_alive()) && time_precise() < drain_deadline)
|
||||
@@ -2434,7 +2437,7 @@ int main(int argc, char** argv)
|
||||
for(auto& worker : workers)
|
||||
kill(worker.first, SIGKILL);
|
||||
for(const auto& worker : task_worker_processes)
|
||||
if(task_worker_alive(worker.pid)) kill(worker.pid, SIGKILL);
|
||||
if(task_worker_alive(worker)) syscall(SYS_pidfd_send_signal, worker.pid_fd, SIGKILL, nullptr, 0);
|
||||
for(auto pid : proactive_compiler_pids)
|
||||
if(proactive_compiler_alive(pid))
|
||||
kill(pid, SIGKILL);
|
||||
|
||||
+14
-7
@@ -1038,20 +1038,20 @@ static bool wasm_source_map_load(const String& path, WasmSourceMap& map)
|
||||
return(!map.rows.empty());
|
||||
}
|
||||
|
||||
static String wasm_source_map_lookup(const WasmSourceMap& map, u64 address)
|
||||
static String wasm_source_map_lookup(const WasmSourceMap& map, u64 address, const String& preferred_file = "")
|
||||
{
|
||||
const WasmSourceMap::Row* found = 0;
|
||||
for(auto& row : map.rows)
|
||||
{
|
||||
if(row.address > address)
|
||||
break;
|
||||
found = &row;
|
||||
auto file = map.files.find(row.file);
|
||||
if(row.line != 0 && file != map.files.end() && (preferred_file == "" || file->second == preferred_file))
|
||||
found = &row;
|
||||
}
|
||||
if(!found || found->line == 0)
|
||||
if(!found)
|
||||
return("");
|
||||
auto file = map.files.find(found->file);
|
||||
if(file == map.files.end())
|
||||
return("");
|
||||
String result = file->second + ":" + std::to_string(found->line);
|
||||
if(found->column)
|
||||
result += ":" + std::to_string(found->column);
|
||||
@@ -2632,6 +2632,10 @@ struct WasmWorkspace : public WasmRequestProfile
|
||||
unit = loaded.mod.get();
|
||||
break;
|
||||
}
|
||||
// Wasmtime can omit the side-module name from interrupted frames.
|
||||
// A single loaded guest remains unambiguous and keeps its source map.
|
||||
if(!unit && frames[index].module == "" && units.size() == 1)
|
||||
unit = units[0].mod.get();
|
||||
if(!unit)
|
||||
continue;
|
||||
String map_path = unit->wasm_path + ".source-map";
|
||||
@@ -2641,14 +2645,17 @@ struct WasmWorkspace : public WasmRequestProfile
|
||||
if(loaded_map == maps.end())
|
||||
{
|
||||
WasmSourceMap source_map;
|
||||
if(!wasm_source_map_load(map_path, source_map) || source_map.module_name != frames[index].module)
|
||||
String expected_module = frames[index].module == "" ? unit->abi.module_name : frames[index].module;
|
||||
if(!wasm_source_map_load(map_path, source_map) || source_map.module_name != expected_module)
|
||||
{
|
||||
unavailable.insert(map_path);
|
||||
continue;
|
||||
}
|
||||
loaded_map = maps.emplace(map_path, std::move(source_map)).first;
|
||||
}
|
||||
String location = wasm_source_map_lookup(loaded_map->second, frames[index].offset);
|
||||
String location = wasm_source_map_lookup(loaded_map->second, frames[index].offset, unit->source_path);
|
||||
if(location == "")
|
||||
location = wasm_source_map_lookup(loaded_map->second, frames[index].offset);
|
||||
// stdlib wrappers are compiler-owned plumbing; their call-site marker maps
|
||||
// failures to user source, and exposing the virtual frame obscures it.
|
||||
if(location == "" || location.rfind("capy://stdlib.capy:", 0) == 0)
|
||||
|
||||
Reference in new issue
Block a user