Module: tools Branch: master Commit: 6475b701e628de35c632cecbf30f74e80aa91700 URL: http://source.winehq.org/git/tools.git/?a=commit;h=6475b701e628de35c632cecbf...
Author: Francois Gouget fgouget@codeweavers.com Date: Mon Feb 25 17:34:18 2013 +0100
testbot/testagentd: Add a wait() RPC that takes a timeout as a parameter.
This is a new RPC which preserves compatibility with old clients.
---
testbot/src/testagentd/platform.h | 6 ++-- testbot/src/testagentd/platform_unix.c | 25 ++++++++++++++++-- testbot/src/testagentd/platform_windows.c | 7 ++++- testbot/src/testagentd/testagentd.c | 38 +++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 10 deletions(-)
diff --git a/testbot/src/testagentd/platform.h b/testbot/src/testagentd/platform.h index 3c25271..d2a3934 100644 --- a/testbot/src/testagentd/platform.h +++ b/testbot/src/testagentd/platform.h @@ -68,12 +68,12 @@ enum run_flags_t { uint64_t platform_run(char** argv, uint32_t flags, char** redirects);
/* If a command was started in the background, waits until either that command - * terminates or the client disconnects (typically because it got tired of - * waiting). + * terminates, the specified timeout (in seconds) expires, or the client + * disconnects (typically because it got tired of waiting). * If no command was started in the background, then reports an error * immediately. */ -int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus); +int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *childstatus);
/* Returns a string describing the last socket-related error */ int sockeintr(void); diff --git a/testbot/src/testagentd/platform_unix.c b/testbot/src/testagentd/platform_unix.c index cd08c58..6552e05 100644 --- a/testbot/src/testagentd/platform_unix.c +++ b/testbot/src/testagentd/platform_unix.c @@ -28,6 +28,7 @@ #include <sys/stat.h> #include <sys/wait.h> #include <signal.h> +#include <time.h>
#include "platform.h" #include "list.h" @@ -125,9 +126,10 @@ uint64_t platform_run(char** argv, uint32_t flags, char** redirects) return pid; }
-int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) +int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *childstatus) { struct child_t* child; + time_t deadline;
LIST_FOR_EACH_ENTRY(child, &children, struct child_t, entry) { @@ -140,10 +142,14 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) return 0; }
+ if (timeout) + deadline = time(NULL) + timeout; while (!child->reaped) { fd_set rfds; char buffer; + struct timeval tv; + int ready;
/* select() blocks until either the client disconnects or until, or * the SIGCHLD signal indicates the child has exited. The recv() call @@ -152,8 +158,21 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) debug("Waiting for " U64FMT "\n", pid); FD_ZERO(&rfds); FD_SET(client, &rfds); - if (select(client+1, &rfds, NULL, NULL, NULL) == 1 && - FD_ISSET(client, &rfds) && + if (timeout) + { + tv.tv_sec = deadline - time(NULL); + if (tv.tv_sec < 0) + tv.tv_sec = 0; + tv.tv_usec = 0; + } + ready = select(client+1, &rfds, NULL, NULL, timeout ? &tv : NULL); + if (ready == 0) + { + /* This is the timeout */ + set_status(ST_ERROR, "timed out waiting for the child process"); + return 0; + } + if (ready == 1 && FD_ISSET(client, &rfds) && recv(client, &buffer, 1, MSG_PEEK | MSG_DONTWAIT) <= 0) { set_status(ST_FATAL, "connection closed"); diff --git a/testbot/src/testagentd/platform_windows.c b/testbot/src/testagentd/platform_windows.c index ab4bf7b..55ed51d 100644 --- a/testbot/src/testagentd/platform_windows.c +++ b/testbot/src/testagentd/platform_windows.c @@ -136,7 +136,7 @@ uint64_t platform_run(char** argv, uint32_t flags, char** redirects) return pi.dwProcessId; }
-int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) +int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *childstatus) { struct child_t *child; HANDLE handles[2]; @@ -160,7 +160,7 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) handles[0] = WSACreateEvent(); WSAEventSelect(client, handles[0], FD_CLOSE); handles[1] = child->handle; - r = WaitForMultipleObjects(2, handles, FALSE, INFINITE); + r = WaitForMultipleObjects(2, handles, FALSE, timeout * 1000);
success = 0; switch (r) @@ -179,6 +179,9 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t *childstatus) else debug("GetExitCodeProcess() failed (%lu). Giving up!\n", GetLastError()); break; + case WAIT_TIMEOUT: + set_status(ST_ERROR, "timed out waiting for the child process"); + return 0; default: debug("WaitForMultipleObjects() returned %lu (le=%lu). Giving up!\n", r, GetLastError()); break; diff --git a/testbot/src/testagentd/testagentd.c b/testbot/src/testagentd/testagentd.c index 837ff02..8a8f2bb 100644 --- a/testbot/src/testagentd/testagentd.c +++ b/testbot/src/testagentd/testagentd.c @@ -29,7 +29,13 @@
#include "platform.h"
-#define PROTOCOL_VERSION "testagentd 1.0" +/* Increase the major version number when making backward-incompatible changes. + * Otherwise increase the minor version number: + * 1.0: Initial release. + * 1.1: Added the wait2 RPC. + */ +#define PROTOCOL_VERSION "testagentd 1.1" + #define BLOCK_SIZE 4096
const char *name0; @@ -73,6 +79,7 @@ enum rpc_ids_t RPCID_RUN, RPCID_WAIT, RPCID_RM, + RPCID_WAIT2, };
/* This is the RPC currently being processed */ @@ -89,6 +96,7 @@ static const char* rpc_name(uint32_t id) "run", "wait", "rm", + "wait2", };
if (id < sizeof(names) / sizeof(*names)) @@ -761,7 +769,30 @@ static void do_wait(SOCKET client) return; }
- if (platform_wait(client, pid, &childstatus)) + if (platform_wait(client, pid, 0, &childstatus)) + { + send_list_size(client, 1); + send_uint32(client, childstatus); + } + else + send_error(client); +} + +static void do_wait2(SOCKET client) +{ + uint64_t pid; + uint32_t timeout; + uint32_t childstatus; + + if (!expect_list_size(client, 2) || + !recv_uint64(client, &pid) || + !recv_uint32(client, &timeout)) + { + send_error(client); + return; + } + + if (platform_wait(client, pid, timeout, &childstatus)) { send_list_size(client, 1); send_uint32(client, childstatus); @@ -906,6 +937,9 @@ static void process_rpc(SOCKET client) case RPCID_WAIT: do_wait(client); break; + case RPCID_WAIT2: + do_wait2(client); + break; case RPCID_RM: do_rm(client); break;