Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions concore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,14 @@ class Concore{
}
}

catch(...){
cout<<"skipping +"<<outpath<<port<<" /"<<name;
catch (const std::exception &e) {
// Surface the error message and rethrow so callers (or the runtime)
// see the failure instead of silently proceeding with truncated data.
std::cerr << e.what() << std::endl;
throw;
} catch (...) {
// Unknown exception: rethrow to avoid silent suppression.
throw;
}
}

Expand All @@ -657,8 +663,11 @@ class Concore{
}
else throw 505;
}
catch(...){
cout<<"skipping +"<<outpath<<port<<" /"<<name;
catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
throw;
} catch (...) {
throw;
}
}

Expand All @@ -683,9 +692,13 @@ class Concore{
outfile<<val[val.size()-1]<<']';
std::string result = outfile.str();
if (result.size() >= SHM_SIZE) {
std::cerr << "ERROR: write_SM payload (" << result.size()
<< " bytes) exceeds " << SHM_SIZE - 1
<< "-byte shared memory limit. Data truncated!" << std::endl;
throw std::runtime_error(
"concore SHM write failed: payload (" +
std::to_string(result.size()) +
" bytes) exceeds SHM_SIZE (" +
std::to_string(SHM_SIZE) +
"). Aborting. No data written. Increase SHM_SIZE in concore.hpp."
);
}
std::strncpy(sharedData_create, result.c_str(), SHM_SIZE - 1);
sharedData_create[SHM_SIZE - 1] = '\0';
Expand All @@ -696,8 +709,11 @@ class Concore{
}
}

catch(...){
cout<<"skipping +"<<outpath<<port<<" /"<<name;
catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
throw;
} catch (...) {
throw;
}
}

Expand All @@ -711,22 +727,29 @@ class Concore{
void write_SM(int port, string name, string val, int delta=0){
chrono::milliseconds timespan((int)(2000*delay));
this_thread::sleep_for(timespan);
if (val.size() >= SHM_SIZE) {
throw std::runtime_error(
"concore SHM write failed: payload (" +
std::to_string(val.size()) +
" bytes) exceeds SHM_SIZE (" +
std::to_string(SHM_SIZE) +
"). Aborting. No data written. Increase SHM_SIZE in concore.hpp."
);
}
try {
if(shmId_create != -1){
if (sharedData_create == nullptr)
throw 506;
if (val.size() >= SHM_SIZE) {
std::cerr << "ERROR: write_SM payload (" << val.size()
<< " bytes) exceeds " << SHM_SIZE - 1
<< "-byte shared memory limit. Data truncated!" << std::endl;
}
std::strncpy(sharedData_create, val.c_str(), SHM_SIZE - 1);
sharedData_create[SHM_SIZE - 1] = '\0';
}
else throw 505;
}
catch(...){
cout<<"skipping +"<<outpath<<port<<" /"<<name;
catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
throw;
} catch (...) {
throw;
}
}

Expand Down
114 changes: 114 additions & 0 deletions tests/test_shm_abort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import shutil
import subprocess
import sys
import tempfile
import textwrap
from pathlib import Path

import pytest


REPO_ROOT = Path(__file__).resolve().parent.parent

pytestmark = pytest.mark.skipif(
shutil.which("g++") is None,
reason="g++ not available",
)


@pytest.fixture(autouse=True)
def _skip_windows():
if sys.platform == "win32":
pytest.skip("SHM requires POSIX")


def _compile_and_run(payload_size):
with tempfile.TemporaryDirectory(prefix="concore_shm_test_") as temp_dir:
temp_path = Path(temp_dir)
(temp_path / "concore.oport").write_text('{"1": "1"}', encoding="utf-8")

source_file = temp_path / "shm_abort_test.cpp"
binary_file = temp_path / "shm_abort_test"
source_file.write_text(
textwrap.dedent(
f"""
#include "concore.hpp"
#include <exception>
#include <filesystem>
#include <string>

int main() {{
try {{
Concore concore;
std::filesystem::create_directories("out/1");
concore.delay = 0;
concore.simtime = 0;
std::string payload({payload_size}, 'a');
concore.write(1, "payload", payload);
if (std::filesystem::exists("out/1/payload")) {{
std::cerr << "write used the file path instead of shared memory" << std::endl;
return 2;
}}
return 0;
}} catch (const std::exception& error) {{
std::cerr << error.what() << std::endl;
return 1;
}}
}}
"""
).lstrip(),
encoding="utf-8",
)

compile_result = subprocess.run(
[
"g++",
"-std=c++17",
"-I",
str(REPO_ROOT),
"-o",
str(binary_file),
str(source_file),
],
capture_output=True,
text=True,
timeout=60,
cwd=temp_path,
)
if compile_result.returncode != 0:
pytest.fail(f"g++ compile failed:\n{compile_result.stderr}")

return subprocess.run(
[str(binary_file)],
capture_output=True,
text=True,
timeout=10,
cwd=temp_path,
)


def test_oversized_payload_throws():
result = _compile_and_run(5000)
assert result.returncode != 0
assert "Aborting" in result.stderr
assert "truncated" not in result.stderr.lower()


def test_within_limit_succeeds():
result = _compile_and_run(100)
assert result.returncode == 0
assert "Aborting" not in result.stderr
assert "write used the file path instead of shared memory" not in result.stderr


def test_exactly_at_limit_throws():
result = _compile_and_run(4096)
assert result.returncode != 0
assert "Aborting" in result.stderr


def test_one_under_limit_succeeds():
result = _compile_and_run(4095)
assert result.returncode == 0
assert "Aborting" not in result.stderr
assert "write used the file path instead of shared memory" not in result.stderr
Loading