From ce94c93aca704b549e6aaeff9d8a32910a52215d Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Mon, 10 Nov 2025 18:04:42 +0530 Subject: [PATCH 1/7] Fix execution in silent mode --- src/xinterpreter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 15d6861b..284a28dd 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -161,11 +161,12 @@ __get_cxx_version () auto cout_strbuf = std::cout.rdbuf(); auto cerr_strbuf = std::cerr.rdbuf(); + std::unique_ptr nullbuf; if (config.silent) { - auto null = xnull(); - std::cout.rdbuf(&null); - std::cerr.rdbuf(&null); + nullbuf = std::make_unique(); + std::cout.rdbuf(nullbuf.get()); + std::cerr.rdbuf(nullbuf.get()); } std::string err; From a4ecd707d933ba63a62294f90b647db9a57edb27 Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Mon, 10 Nov 2025 18:23:24 +0530 Subject: [PATCH 2/7] Add tests --- test/test_interpreter.cpp | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/test_interpreter.cpp b/test/test_interpreter.cpp index 5ce9d540..292d4bee 100644 --- a/test/test_interpreter.cpp +++ b/test/test_interpreter.cpp @@ -1136,3 +1136,44 @@ TEST_CASE("C and C++ stdout/stderr capture") REQUIRE(captured_err.find("C stderr") != std::string::npos); REQUIRE(captured_err.find("C++ stderr") != std::string::npos); } + +TEST_CASE("Silent mode suppresses C and C++ stdout/stderr") +{ + std::vector Args = {}; + xcpp::interpreter interpreter((int)Args.size(), Args.data()); + + xeus::execute_request_config config; + // forcing silent as true + config.silent = true; + config.store_history = false; + config.allow_stdin = false; + + nl::json header = nl::json::object(); + xeus::xrequest_context::guid_list id = {}; + xeus::xrequest_context context(header, id); + + std::promise promise; + auto callback = [&promise](nl::json result) { promise.set_value(result); }; + + StreamRedirectRAII cout_redirect(std::cout); + StreamRedirectRAII cerr_redirect(std::cerr); + + std::string code = R"( + #include + #include + printf("C stdout\n"); + fprintf(stderr, "C stderr\n"); + std::cout << "C++ stdout\n"; + std::cerr << "C++ stderr\n"; + )"; + + interpreter.execute_request(context, callback, code, config, nl::json::object()); + (void)promise.get_future().get(); + + std::string captured_out = cout_redirect.getCaptured(); + std::string captured_err = cerr_redirect.getCaptured(); + + // Nothing should reach the redirected streams in silent mode + REQUIRE(captured_out.empty()); + REQUIRE(captured_err.empty()); +} From 688113b759e567ca90ed618363cbed11922209d2 Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Wed, 29 Apr 2026 18:20:09 +0530 Subject: [PATCH 3/7] Use an RAII guard for the silent mode --- src/xinterpreter.cpp | 51 ++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index b91ff1d6..3de3e5c6 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -236,6 +236,38 @@ namespace xcpp return "unknown"; } + class SilentStreamRedirectRAII + { + public: + explicit SilentStreamRedirectRAII(bool silent) + : m_silent(silent), + m_old_cout(silent ? std::cout.rdbuf() : nullptr), + m_old_cerr(silent ? std::cerr.rdbuf() : nullptr) + { + if (m_silent) + { + std::cout.rdbuf(&m_null); + std::cerr.rdbuf(&m_null); + } + } + + ~SilentStreamRedirectRAII() noexcept + { + if (m_silent) + { + std::cout.rdbuf(m_old_cout); + std::cerr.rdbuf(m_old_cerr); + } + } + + private: + bool m_silent; + xnull m_null; + + std::streambuf* m_old_cout; + std::streambuf* m_old_cerr; + }; + interpreter::interpreter(int argc, const char* const* argv) : xmagics() , p_cout_strbuf(nullptr) @@ -288,17 +320,7 @@ namespace xcpp // If silent is set to true, temporarily dismiss all std::cerr and // std::cout outputs resulting from `process_code`. - - auto cout_strbuf = std::cout.rdbuf(); - auto cerr_strbuf = std::cerr.rdbuf(); - - std::unique_ptr nullbuf; - if (config.silent) - { - nullbuf = std::make_unique(); - std::cout.rdbuf(nullbuf.get()); - std::cerr.rdbuf(nullbuf.get()); - } + SilentStreamRedirectRAII silent_guard(config.silent); std::string err; @@ -332,13 +354,6 @@ namespace xcpp std::cout << std::flush; std::cerr << std::flush; - // Reset non-silent output buffers - if (config.silent) - { - std::cout.rdbuf(cout_strbuf); - std::cerr.rdbuf(cerr_strbuf); - } - // Depending of error level, publish execution result or execution // error, and compose execute_reply message. if (errorlevel) From b6e8c1f3dccf409c10146b842d4155bbc8448ae9 Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Wed, 29 Apr 2026 18:22:19 +0530 Subject: [PATCH 4/7] git format recommendation --- src/xinterpreter.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 3de3e5c6..b0812750 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -239,10 +239,11 @@ namespace xcpp class SilentStreamRedirectRAII { public: + explicit SilentStreamRedirectRAII(bool silent) - : m_silent(silent), - m_old_cout(silent ? std::cout.rdbuf() : nullptr), - m_old_cerr(silent ? std::cerr.rdbuf() : nullptr) + : m_silent(silent) + , m_old_cout(silent ? std::cout.rdbuf() : nullptr) + , m_old_cerr(silent ? std::cerr.rdbuf() : nullptr) { if (m_silent) { @@ -261,6 +262,7 @@ namespace xcpp } private: + bool m_silent; xnull m_null; From c62725e15b4e8775607b72a3b7b26d02c7dd4d7e Mon Sep 17 00:00:00 2001 From: Anutosh Bhat Date: Wed, 29 Apr 2026 18:29:02 +0530 Subject: [PATCH 5/7] Increase initial memory allocation to 128MB --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 10fb803d..bd3779ad 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -69,7 +69,7 @@ if(EMSCRIPTEN) PUBLIC "SHELL: -s ASSERTIONS=0" PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1" PUBLIC "SHELL: -s STACK_SIZE=32mb" - PUBLIC "SHELL: -s INITIAL_MEMORY=64MB" + PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" PUBLIC "SHELL: --preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" PUBLIC "SHELL: --preload-file ../${XEUS_CPP_DATA_DIR}@/share/xeus-cpp" PUBLIC "SHELL: --preload-file ../${XEUS_CPP_CONF_DIR}@/etc/xeus-cpp" From 7ccb8b2423e07b6d5cd92743152b3850cb4a97ed Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Wed, 29 Apr 2026 18:38:33 +0530 Subject: [PATCH 6/7] Skip test for emscripten --- test/CMakeLists.txt | 2 +- test/test_interpreter.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd3779ad..10fb803d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -69,7 +69,7 @@ if(EMSCRIPTEN) PUBLIC "SHELL: -s ASSERTIONS=0" PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1" PUBLIC "SHELL: -s STACK_SIZE=32mb" - PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" + PUBLIC "SHELL: -s INITIAL_MEMORY=64MB" PUBLIC "SHELL: --preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" PUBLIC "SHELL: --preload-file ../${XEUS_CPP_DATA_DIR}@/share/xeus-cpp" PUBLIC "SHELL: --preload-file ../${XEUS_CPP_CONF_DIR}@/etc/xeus-cpp" diff --git a/test/test_interpreter.cpp b/test/test_interpreter.cpp index f383864f..a1a11f57 100644 --- a/test/test_interpreter.cpp +++ b/test/test_interpreter.cpp @@ -1230,6 +1230,8 @@ TEST_SUITE("mime_bundle_repr") } } +#if !defined(__EMSCRIPTEN__) +// TODO: Currently any test added to this file will fail for the wasm build saying memory access out of bounds. TEST_CASE("Silent mode restores std::cout and std::cerr buffers") { std::vector Args = {}; @@ -1264,3 +1266,4 @@ TEST_CASE("Silent mode restores std::cout and std::cerr buffers") REQUIRE(std::cout.rdbuf() == cout_before); REQUIRE(std::cerr.rdbuf() == cerr_before); } +#endif \ No newline at end of file From ddc303dbb19bdadbaf820600004f98883201912b Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Wed, 29 Apr 2026 19:24:35 +0530 Subject: [PATCH 7/7] Delete copy & move operations --- src/xinterpreter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index b0812750..b1913461 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -261,6 +261,11 @@ namespace xcpp } } + SilentStreamRedirectRAII(const SilentStreamRedirectRAII&) = delete; + SilentStreamRedirectRAII& operator=(const SilentStreamRedirectRAII&) = delete; + SilentStreamRedirectRAII(SilentStreamRedirectRAII&&) = delete; + SilentStreamRedirectRAII& operator=(SilentStreamRedirectRAII&&) = delete; + private: bool m_silent;