Skip to content

Commit 587c32b

Browse files
authored
fix: another edge case of Uncaught null (#587)
* fix: another edge case of `Uncaught null` * stamp: adjust cpu time
1 parent 0650362 commit 587c32b

File tree

4 files changed

+157
-4
lines changed

4 files changed

+157
-4
lines changed

crates/base/src/runtime/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,8 +1573,9 @@ where
15731573
}
15741574

15751575
let js_runtime = &mut this.js_runtime;
1576+
let op_state = js_runtime.op_state();
15761577
let cpu_metrics_guard = get_cpu_metrics_guard(
1577-
js_runtime.op_state(),
1578+
op_state.clone(),
15781579
maybe_cpu_usage_metrics_tx,
15791580
accumulated_cpu_time_ns,
15801581
);
@@ -1630,15 +1631,22 @@ where
16301631
beforeunload_cpu_threshold.load().as_deref().copied()
16311632
{
16321633
let threshold_ns = (threshold_ms as i128) * 1_000_000;
1633-
let accumulated_cpu_time_ns = *accumulated_cpu_time_ns as i128;
1634-
1635-
if accumulated_cpu_time_ns >= threshold_ns {
1634+
if (*accumulated_cpu_time_ns as i128) >= threshold_ns {
16361635
beforeunload_cpu_threshold.store(None);
16371636

16381637
if !state.is_terminated() {
1638+
let _cpu_metrics_guard = get_cpu_metrics_guard(
1639+
op_state.clone(),
1640+
maybe_cpu_usage_metrics_tx,
1641+
accumulated_cpu_time_ns,
1642+
);
1643+
16391644
if let Err(err) = MaybeDenoRuntime::DenoRuntime(&mut this)
16401645
.dispatch_beforeunload_event(WillTerminateReason::CPU)
16411646
{
1647+
if state.is_terminated() {
1648+
return Poll::Ready(Err(anyhow!("execution terminated")));
1649+
}
16421650
return Poll::Ready(Err(err));
16431651
}
16441652
}
@@ -1662,9 +1670,18 @@ where
16621670
beforeunload_mem_threshold.store(None);
16631671

16641672
if !state.is_terminated() && !mem_state.is_exceeded() {
1673+
let _cpu_metrics_guard = get_cpu_metrics_guard(
1674+
op_state,
1675+
maybe_cpu_usage_metrics_tx,
1676+
accumulated_cpu_time_ns,
1677+
);
1678+
16651679
if let Err(err) = MaybeDenoRuntime::DenoRuntime(&mut this)
16661680
.dispatch_beforeunload_event(WillTerminateReason::Memory)
16671681
{
1682+
if state.is_terminated() {
1683+
return Poll::Ready(Err(anyhow!("execution terminated")));
1684+
}
16681685
return Poll::Ready(Err(err));
16691686
}
16701687
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function mySlowFunction(baseNumber) {
2+
console.time("mySlowFunction");
3+
let now = Date.now();
4+
let result = 0;
5+
for (var i = Math.pow(baseNumber, 7); i >= 0; i--) {
6+
result += Math.atan(i) * Math.tan(i);
7+
}
8+
let duration = Date.now() - now;
9+
console.timeEnd("mySlowFunction");
10+
return { result: result, duration: duration };
11+
}
12+
13+
let keep = true;
14+
15+
async function sleep(ms: number) {
16+
return new Promise((res) => {
17+
setTimeout(() => {
18+
res(void 0);
19+
}, ms);
20+
});
21+
}
22+
23+
setInterval(() => {
24+
if (keep) {
25+
mySlowFunction(10);
26+
}
27+
}, 800);
28+
29+
addEventListener("beforeunload", () => {
30+
keep = false;
31+
while (true) {
32+
mySlowFunction(10);
33+
console.log("cpu");
34+
}
35+
});
36+
37+
const never = new Promise(() => {});
38+
EdgeRuntime.waitUntil(never);
39+
40+
Deno.serve((_req) => new Response("Hello, world"));
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
function mySlowFunction(baseNumber) {
2+
console.time("mySlowFunction");
3+
let now = Date.now();
4+
let result = 0;
5+
for (var i = Math.pow(baseNumber, 7); i >= 0; i--) {
6+
result += Math.atan(i) * Math.tan(i);
7+
}
8+
let duration = Date.now() - now;
9+
console.timeEnd("mySlowFunction");
10+
return { result: result, duration: duration };
11+
}
12+
13+
let keep = true;
14+
15+
async function sleep(ms: number) {
16+
return new Promise((res) => {
17+
setTimeout(() => {
18+
res(void 0);
19+
}, ms);
20+
});
21+
}
22+
23+
const arr: ArrayBuffer[] = [];
24+
25+
setInterval(async () => {
26+
if (keep) {
27+
await sleep(300);
28+
arr.push(new ArrayBuffer(1024 * 1024));
29+
}
30+
}, 800);
31+
32+
addEventListener("beforeunload", () => {
33+
keep = false;
34+
while (true) {
35+
arr.push(new ArrayBuffer(1024 * 1024));
36+
console.log("mem");
37+
}
38+
});
39+
40+
const never = new Promise(() => {});
41+
EdgeRuntime.waitUntil(never);
42+
43+
Deno.serve((_req) => new Response("Hello, world"));

crates/base/tests/integration_tests.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,59 @@ async fn test_issue_func_205() {
25532553
unreachable!("test failed");
25542554
}
25552555

2556+
#[tokio::test]
2557+
#[serial]
2558+
async fn test_issue_func_280() {
2559+
async fn run(func_name: &'static str, reason: ShutdownReason) {
2560+
let (tx, mut rx) = mpsc::unbounded_channel();
2561+
let tb = TestBedBuilder::new("./test_cases/main")
2562+
.with_per_worker_policy(None)
2563+
.with_worker_event_sender(Some(tx))
2564+
.with_server_flags(ServerFlags {
2565+
beforeunload_cpu_pct: Some(90),
2566+
beforeunload_memory_pct: Some(90),
2567+
..Default::default()
2568+
})
2569+
.build()
2570+
.await;
2571+
2572+
let resp = tb
2573+
.request(|b| {
2574+
b.uri("/meow")
2575+
.header("x-cpu-time-soft-limit-ms", HeaderValue::from_static("1000"))
2576+
.header("x-cpu-time-hard-limit-ms", HeaderValue::from_static("2000"))
2577+
.header("x-memory-limit-mb", "30")
2578+
.header("x-service-path", format!("issue-func-280/{}", func_name))
2579+
.body(Body::empty())
2580+
.context("can't make request")
2581+
})
2582+
.await
2583+
.unwrap();
2584+
2585+
assert_eq!(resp.status().as_u16(), StatusCode::OK);
2586+
2587+
while let Some(ev) = rx.recv().await {
2588+
match ev.event {
2589+
WorkerEvents::Log(ev) => {
2590+
tracing::info!("{}", ev.msg);
2591+
continue;
2592+
}
2593+
WorkerEvents::Shutdown(ev) => {
2594+
tb.exit(Duration::from_secs(TESTBED_DEADLINE_SEC)).await;
2595+
assert_eq!(ev.reason, reason);
2596+
return;
2597+
}
2598+
_ => continue,
2599+
}
2600+
}
2601+
2602+
unreachable!("test failed");
2603+
}
2604+
2605+
run("cpu", ShutdownReason::CPUTime).await;
2606+
run("mem", ShutdownReason::Memory).await;
2607+
}
2608+
25562609
#[tokio::test]
25572610
#[serial]
25582611
async fn test_should_render_detailed_failed_to_create_graph_error() {

0 commit comments

Comments
 (0)