Skip to content

Commit 8bbac27

Browse files
committed
fix: keep Ctrl-C raised while releasing freed memory after rules, and make the compile interrupt test deterministic
1 parent 30b3806 commit 8bbac27

4 files changed

Lines changed: 20 additions & 5 deletions

File tree

‎crates/sqlbuild-python/src/bindings/_helpers/rules/rule_plan.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub(crate) fn plan_rule_run<'py>(
3333
let py: Python<'py> = options.py();
3434
let graph: Bound<'py, PyAny> = options.get("graph")?;
3535
let project: Bound<'py, PyAny> = field(&graph, "project")?;
36-
freed_memory_released(py);
36+
freed_memory_released(py)?;
3737
let effective_config: Bound<'py, PyAny> =
3838
resolved_ignore_selectors(&options.get("config")?, &project)?;
3939
let project_dir: Bound<'py, PyAny> = options.get("project_dir")?.call_method0("resolve")?;

‎crates/sqlbuild-python/src/bindings/_helpers/rules/rule_run.rs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::collections::BTreeSet;
44
use std::path::PathBuf;
55

6+
use pyo3::exceptions::PyException;
67
use pyo3::prelude::{Bound, PyAny, PyAnyMethods, PyModule, PyModuleMethods, PyResult, Python};
78
use pyo3::types::{PyDict, PyTuple, PyTupleMethods};
89
use pyo3::{IntoPyObjectExt, pyfunction, wrap_pyfunction};
@@ -145,16 +146,19 @@ fn rules_bulk_cache_path(project_dir: PathBuf, file_name: &str) -> PathBuf {
145146
}
146147

147148
/// Hand freed glibc heap pages back to the OS; a no-op elsewhere or without `malloc_trim`.
148-
pub(crate) fn freed_memory_released(py: Python<'_>) {
149+
pub(crate) fn freed_memory_released(py: Python<'_>) -> PyResult<()> {
149150
if !cfg!(target_os = "linux") {
150-
return;
151+
return Ok(());
151152
}
152153
let trim = || -> PyResult<()> {
153154
let process: Bound<'_, PyAny> = imported(py, CTYPES_MODULE, "CDLL")?.call1((py.None(),))?;
154155
let _ = native_field(&process, "malloc_trim")?.call1((0,))?;
155156
Ok(())
156157
};
157-
let _ = trim();
158+
match trim() {
159+
Err(error) if !error.is_instance_of::<PyException>(py) => Err(error),
160+
_ => Ok(()),
161+
}
158162
}
159163

160164
pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {

‎tests/e2e/src/sqlbuild/cli/commands/main/compile/helpers.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4966,6 +4966,8 @@ def compile_with_binding_error(project_dir: Path) -> dict[str, Any]:
49664966
"import time\n\n\n"
49674967
"def slow_total(amount: str) -> str:\n"
49684968
' """Return the amount, pausing for the macro tests that only SQL lint expands."""\n'
4969+
" if amount == 'model_amount':\n"
4970+
" time.sleep(2.0)\n"
49694971
" if amount == 'slow_amount':\n"
49704972
" with open(os.environ['SLOW_MACRO_MARKER'], 'a', encoding='utf-8') as marker:\n"
49714973
" marker.write('expanding\\n')\n"
@@ -4985,7 +4987,8 @@ def slow_lint_model_files(*, model_count: int) -> dict[str, str]:
49854987
),
49864988
"models/slow_total.sql": (
49874989
'MODEL (description "Slow total");\n'
4988-
'SELECT @slow_total("amount") AS amount FROM (SELECT 5 AS amount) AS input_values\n'
4990+
'SELECT @slow_total("model_amount") AS amount\n'
4991+
"FROM (SELECT 5 AS model_amount) AS input_values\n"
49894992
),
49904993
**{
49914994
f"tests/slow_total_{index}.sql": (
@@ -5001,3 +5004,9 @@ def slow_lint_model_files(*, model_count: int) -> dict[str, str]:
50015004
for index in range(model_count)
50025005
},
50035006
}
5007+
5008+
5009+
def restore_default_interrupt() -> None:
5010+
"""Give a spawned command default Ctrl-C handling even when its parent ignores SIGINT."""
5011+
5012+
_ = signal.signal(signal.SIGINT, signal.SIG_DFL)

‎tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_early_lint.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import (
2020
compile_json_payload,
2121
diagnostic_location_keys,
22+
restore_default_interrupt,
2223
slow_lint_model_files,
2324
)
2425
from tests.e2e.src.sqlbuild.cli.commands.shared.helpers import prepare_inline_project
@@ -132,6 +133,7 @@ def test_given_slow_background_lint_when_interrupted_then_compile_stops_promptly
132133
"SLOW_MACRO_MARKER": str(marker),
133134
"SLOW_MACRO_SECONDS": str(test_case.macro_seconds),
134135
},
136+
preexec_fn=restore_default_interrupt,
135137
)
136138
deadline: float = time.monotonic() + 60.0
137139
while not marker.exists() and time.monotonic() < deadline and process.poll() is None:

0 commit comments

Comments
 (0)