mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
Make a version of tor_read_all_handle() for non-Windows platforms
Mainly used for testing reading from subprocesses. To be more generic we now pass in a pointer to a process_handle_t rather than a Windows- specific HANDLE.
This commit is contained in:
parent
76fde28475
commit
5b8a20ed44
@ -3522,7 +3522,8 @@ tor_get_exit_code(const process_handle_t process_handle,
|
|||||||
* only once the process has exited, or <b>count</b> bytes are read. Returns
|
* only once the process has exited, or <b>count</b> bytes are read. Returns
|
||||||
* the number of bytes read, or -1 on error. */
|
* the number of bytes read, or -1 on error. */
|
||||||
ssize_t
|
ssize_t
|
||||||
tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
|
tor_read_all_handle(HANDLE h, char *buf, size_t count,
|
||||||
|
const process_handle_t *process)
|
||||||
{
|
{
|
||||||
size_t numread = 0;
|
size_t numread = 0;
|
||||||
BOOL retval;
|
BOOL retval;
|
||||||
@ -3544,7 +3545,7 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
|
|||||||
/* Nothing available: process exited or it is busy */
|
/* Nothing available: process exited or it is busy */
|
||||||
|
|
||||||
/* Exit if we don't know whether the process is running */
|
/* Exit if we don't know whether the process is running */
|
||||||
if (NULL == hProcess)
|
if (NULL == process)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* The process exited and there's nothing left to read from it */
|
/* The process exited and there's nothing left to read from it */
|
||||||
@ -3554,7 +3555,8 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
|
|||||||
/* If process is not running, check for output one more time in case
|
/* If process is not running, check for output one more time in case
|
||||||
it wrote something after the peek was performed. Otherwise keep on
|
it wrote something after the peek was performed. Otherwise keep on
|
||||||
waiting for output */
|
waiting for output */
|
||||||
byte_count = WaitForSingleObject(hProcess, 0);
|
tor_assert(process != NULL);
|
||||||
|
byte_count = WaitForSingleObject(process->pid.hProcess, 0);
|
||||||
if (WAIT_TIMEOUT != byte_count)
|
if (WAIT_TIMEOUT != byte_count)
|
||||||
process_exited = TRUE;
|
process_exited = TRUE;
|
||||||
|
|
||||||
@ -3576,31 +3578,77 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
|
|||||||
}
|
}
|
||||||
return (ssize_t)numread;
|
return (ssize_t)numread;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
|
||||||
|
* <b>process</b> is NULL, the function will return immediately if there is
|
||||||
|
* nothing more to read. Otherwise data will be read until end of file, or
|
||||||
|
* <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
|
||||||
|
* error. */
|
||||||
|
ssize_t
|
||||||
|
tor_read_all_handle(FILE *h, char *buf, size_t count,
|
||||||
|
const process_handle_t *process)
|
||||||
|
{
|
||||||
|
size_t numread = 0;
|
||||||
|
char *retval;
|
||||||
|
|
||||||
|
if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (numread != count) {
|
||||||
|
/* Use fgets because that is what we use in log_from_pipe() */
|
||||||
|
retval = fgets(buf+numread, (int)(count-numread), h);
|
||||||
|
if (NULL == retval) {
|
||||||
|
if (feof(h)) {
|
||||||
|
fclose(h);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (EAGAIN == errno) {
|
||||||
|
if (process)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
log_warn(LD_GENERAL, "fgets() from handle failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
fclose(h);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tor_assert(retval != NULL);
|
||||||
|
numread += strlen(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug(LD_GENERAL, "fgets read %d bytes from handle", (int)numread);
|
||||||
|
return (ssize_t)numread;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Read from stdout of a process until the process exits. */
|
/** Read from stdout of a process until the process exits. */
|
||||||
ssize_t
|
ssize_t
|
||||||
tor_read_all_from_process_stdout(const process_handle_t process_handle,
|
tor_read_all_from_process_stdout(const process_handle_t *process_handle,
|
||||||
char *buf, size_t count)
|
char *buf, size_t count)
|
||||||
{
|
{
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return tor_read_all_handle(process_handle.stdout_pipe, buf, count,
|
return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
|
||||||
process_handle.pid.hProcess);
|
process_handle);
|
||||||
#else
|
#else
|
||||||
return read_all(process_handle.stdout_pipe, buf, count, 0);
|
return tor_read_all_handle(process_handle->stdout_handle, buf, count,
|
||||||
|
process_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read from stdout of a process until the process exits. */
|
/** Read from stdout of a process until the process exits. */
|
||||||
ssize_t
|
ssize_t
|
||||||
tor_read_all_from_process_stderr(const process_handle_t process_handle,
|
tor_read_all_from_process_stderr(const process_handle_t *process_handle,
|
||||||
char *buf, size_t count)
|
char *buf, size_t count)
|
||||||
{
|
{
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return tor_read_all_handle(process_handle.stderr_pipe, buf, count,
|
return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
|
||||||
process_handle.pid.hProcess);
|
process_handle);
|
||||||
#else
|
#else
|
||||||
return read_all(process_handle.stderr_pipe, buf, count, 0);
|
return tor_read_all_handle(process_handle->stderr_handle, buf, count,
|
||||||
|
process_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,12 +388,15 @@ int tor_get_exit_code(const process_handle_t process_handle,
|
|||||||
int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
|
int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
|
ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
|
||||||
HANDLE hProcess);
|
const process_handle_t *process);
|
||||||
|
#else
|
||||||
|
ssize_t tor_read_all_handle(FILE *h, char *buf, size_t count,
|
||||||
|
const process_handle_t *process);
|
||||||
#endif
|
#endif
|
||||||
ssize_t tor_read_all_from_process_stdout(const process_handle_t process_handle,
|
ssize_t tor_read_all_from_process_stdout(
|
||||||
char *buf, size_t count);
|
const process_handle_t *process_handle, char *buf, size_t count);
|
||||||
ssize_t tor_read_all_from_process_stderr(const process_handle_t process_handle,
|
ssize_t tor_read_all_from_process_stderr(
|
||||||
char *buf, size_t count);
|
const process_handle_t *process_handle, char *buf, size_t count);
|
||||||
char *tor_join_win_cmdline(const char *argv[]);
|
char *tor_join_win_cmdline(const char *argv[]);
|
||||||
void format_helper_exit_status(unsigned char child_state,
|
void format_helper_exit_status(unsigned char child_state,
|
||||||
int saved_errno, char *hex_errno);
|
int saved_errno, char *hex_errno);
|
||||||
|
@ -1404,8 +1404,8 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
|
|||||||
tt_int_op(process_handle.stderr_pipe, >, 0);
|
tt_int_op(process_handle.stderr_pipe, >, 0);
|
||||||
|
|
||||||
/* Check stdout */
|
/* Check stdout */
|
||||||
pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
|
pos = tor_read_all_from_process_stdout(&process_handle, stdout_buf,
|
||||||
sizeof(stdout_buf) - 1);
|
sizeof(stdout_buf) - 1);
|
||||||
tt_assert(pos >= 0);
|
tt_assert(pos >= 0);
|
||||||
stdout_buf[pos] = '\0';
|
stdout_buf[pos] = '\0';
|
||||||
tt_str_op(stdout_buf, ==, expected_out);
|
tt_str_op(stdout_buf, ==, expected_out);
|
||||||
@ -1418,7 +1418,7 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
|
|||||||
// TODO: Make test-child exit with something other than 0
|
// TODO: Make test-child exit with something other than 0
|
||||||
|
|
||||||
/* Check stderr */
|
/* Check stderr */
|
||||||
pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
|
pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
|
||||||
sizeof(stderr_buf) - 1);
|
sizeof(stderr_buf) - 1);
|
||||||
tt_assert(pos >= 0);
|
tt_assert(pos >= 0);
|
||||||
stderr_buf[pos] = '\0';
|
stderr_buf[pos] = '\0';
|
||||||
@ -1493,57 +1493,66 @@ test_util_spawn_background_partial_read(void *ptr)
|
|||||||
"DONE\r\n",
|
"DONE\r\n",
|
||||||
NULL };
|
NULL };
|
||||||
const char *expected_err = "ERR\r\n";
|
const char *expected_err = "ERR\r\n";
|
||||||
int expected_out_ctr;
|
|
||||||
#else
|
#else
|
||||||
const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
|
const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
|
||||||
const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
|
const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
|
||||||
const char *expected_err = "ERR\r\n";
|
"DONE\n",
|
||||||
|
NULL };
|
||||||
|
const char *expected_err = "ERR\n";
|
||||||
#endif
|
#endif
|
||||||
|
int expected_out_ctr;
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
|
|
||||||
/* Start the program */
|
/* Start the program */
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
tor_spawn_background(NULL, argv, &process_handle);
|
tor_spawn_background(NULL, argv, &process_handle);
|
||||||
|
#else
|
||||||
|
tor_spawn_background(argv[0], argv, &process_handle);
|
||||||
|
#endif
|
||||||
tt_int_op(process_handle.status, ==, expected_status);
|
tt_int_op(process_handle.status, ==, expected_status);
|
||||||
|
|
||||||
/* Check stdout */
|
/* Check stdout */
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
for (expected_out_ctr =0; expected_out[expected_out_ctr] != NULL;) {
|
for (expected_out_ctr =0; expected_out[expected_out_ctr] != NULL;) {
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
|
pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
|
||||||
sizeof(stdout_buf) - 1, NULL);
|
sizeof(stdout_buf) - 1, NULL);
|
||||||
|
#else
|
||||||
|
pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
|
||||||
|
sizeof(stdout_buf) - 1, NULL);
|
||||||
|
#endif
|
||||||
log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
|
log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
|
||||||
|
|
||||||
/* We would have blocked, keep on trying */
|
/* We would have blocked, keep on trying */
|
||||||
if (0 == pos)
|
if (0 == pos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tt_assert(pos >= 0);
|
tt_int_op(pos, >=, 0);
|
||||||
stdout_buf[pos] = '\0';
|
stdout_buf[pos] = '\0';
|
||||||
tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
|
tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
|
||||||
tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
|
tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
|
||||||
expected_out_ctr++;
|
expected_out_ctr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The process should have exited without writing more */
|
/* The process should have exited without writing more */
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
|
pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
|
||||||
sizeof(stdout_buf) - 1,
|
sizeof(stdout_buf) - 1,
|
||||||
process_handle.pid.hProcess);
|
&process_handle);
|
||||||
tt_int_op(pos, ==, 0);
|
|
||||||
#else
|
#else
|
||||||
pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
|
pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
|
||||||
sizeof(stdout_buf) - 1);
|
sizeof(stdout_buf) - 1,
|
||||||
tt_assert(pos >= 0);
|
&process_handle);
|
||||||
stdout_buf[pos] = '\0';
|
|
||||||
tt_str_op(stdout_buf, ==, expected_out);
|
|
||||||
tt_int_op(pos, ==, strlen(expected_out));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check it terminated correctly */
|
/* Check it terminated correctly */
|
||||||
retval = tor_get_exit_code(process_handle, 1, &exit_code);
|
retval = tor_get_exit_code(process_handle, 1, &exit_code);
|
||||||
tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
|
tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
|
||||||
tt_int_op(exit_code, ==, expected_exit);
|
tt_int_op(exit_code, ==, expected_exit);
|
||||||
|
|
||||||
// TODO: Make test-child exit with something other than 0
|
// TODO: Make test-child exit with something other than 0
|
||||||
|
|
||||||
/* Check stderr */
|
/* Check stderr */
|
||||||
pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
|
pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
|
||||||
sizeof(stderr_buf) - 1);
|
sizeof(stderr_buf) - 1);
|
||||||
tt_assert(pos >= 0);
|
tt_assert(pos >= 0);
|
||||||
stderr_buf[pos] = '\0';
|
stderr_buf[pos] = '\0';
|
||||||
|
Loading…
Reference in New Issue
Block a user