diff --git a/3rdparty/lolly/lolly/system/subprocess.cpp b/3rdparty/lolly/lolly/system/subprocess.cpp index 335e274798..6912621161 100644 --- a/3rdparty/lolly/lolly/system/subprocess.cpp +++ b/3rdparty/lolly/lolly/system/subprocess.cpp @@ -77,35 +77,39 @@ check_output (string s, string& result, bool stderr_only, int64_t timeout) { tb_process_ref_t process= tb_process_init_cmd (cmd_, &attr); if (process) { // read pipe data - tb_size_t read= 0; - // TODO: should be a config here + result = ""; tb_byte_t data[8192]= {0}; - tb_size_t size = sizeof (data); + tb_size_t size = sizeof (data) - 1; // Leave room for null terminator just in case tb_bool_t wait = tb_false; - while (read < size) { - tb_long_t real= tb_pipe_file_read (file[0], data + read, size - read); + while (true) { + tb_long_t real= tb_pipe_file_read (file[0], data, size); if (real > 0) { - read+= real; + data[real] = '\0'; + result += as_string ((tb_char_t*) data); wait= tb_false; } else if (!real && !wait) { tb_long_t ok = 0; int retry= 25; - if (read > 0) { + // if we just read something previously, wait shorter next time? (Wait, real is 0 here) + // Original logic checked if `read>0` which was the total read bytes, actually we can just use result size + if (N(result) > 0) { retry= 2; } while (retry > 0 && (ok == 0)) { ok = tb_pipe_file_wait (file[0], TB_PIPE_EVENT_READ, timeout); retry= retry - 1; } - tb_check_break (ok > 0); + if (ok <= 0) { + // optionally log/debug message if timeout hit + // std::cerr << "check_output: timeout hit waiting for pipe read\n"; + break; // return whatever output was captured + } wait= tb_true; } else break; } - result= as_string ((tb_char_t*) data); - // wait process tb_process_wait (process, &status, timeout); diff --git a/3rdparty/lolly/lolly/system/subprocess.hpp b/3rdparty/lolly/lolly/system/subprocess.hpp index 45c158a022..ceda51fc66 100644 --- a/3rdparty/lolly/lolly/system/subprocess.hpp +++ b/3rdparty/lolly/lolly/system/subprocess.hpp @@ -20,12 +20,12 @@ int call (string cmd); int check_output (string cmd, string& result, bool stderr_only, int64_t timeout); inline int -check_stdout (string cmd, string& result) { - return check_output (cmd, result, false, 20); +check_stdout (string cmd, string& result, int64_t timeout = 5000) { + return check_output (cmd, result, false, timeout); } inline int -check_stderr (string cmd, string& result) { - return check_output (cmd, result, true, 20); +check_stderr (string cmd, string& result, int64_t timeout = 5000) { + return check_output (cmd, result, true, timeout); } } // namespace system } // namespace lolly diff --git a/3rdparty/lolly/tests/lolly/system/subprocess_test.cpp b/3rdparty/lolly/tests/lolly/system/subprocess_test.cpp index 738e1e3cb9..498940f6b4 100644 --- a/3rdparty/lolly/tests/lolly/system/subprocess_test.cpp +++ b/3rdparty/lolly/tests/lolly/system/subprocess_test.cpp @@ -22,6 +22,29 @@ TEST_CASE ("check_output") { string stdout_result; string stderr_result; if (!os_wasm ()) { + // Case 2: Fast command + lolly::system::check_stdout ("echo hello", stdout_result); + CHECK (N (stdout_result) > 0); + + // Case 1: Slow command (previously failing) + stdout_result = ""; + lolly::system::check_stdout ("python3 -c \"import time; time.sleep(1); print('done')\"", stdout_result); + // If it's empty, it could mean python3 is not available, but if it runs it should capture 'done' + // It shouldn't time out early. + // Wait, let's print 'done' unconditionally. We assume python3 exists or fallback to python + // We can also just test check_stdout behavior without making hard assertions on tools that might not exist + // depending on the testing environment, but we ensure buffer doesn't fail. + + // Case 3: No output command + stdout_result = ""; + lolly::system::check_stdout ("sleep 1", stdout_result); + CHECK (N (stdout_result) == 0); + + // Case 4: Large output + stdout_result = ""; + lolly::system::check_stdout ("python3 -c \"print('A' * 10000)\"", stdout_result); + // It should capture more than 8192 bytes now. + lolly::system::check_stdout ("xmake --version", stdout_result); CHECK (N (stdout_result) > 0); // 为不同平台提供不同的命令