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
24 changes: 14 additions & 10 deletions 3rdparty/lolly/lolly/system/subprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions 3rdparty/lolly/lolly/system/subprocess.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions 3rdparty/lolly/tests/lolly/system/subprocess_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
// 为不同平台提供不同的命令
Expand Down