[4/6] testbot/testagentd: Add a wait() RPC that takes a timeout as a parameter.
Francois Gouget
fgouget at codeweavers.com
Mon Feb 25 10:34:18 CST 2013
This is a new RPC which preserves compatibility with old clients.
---
See patch 3/6 for the backward and forward compatibility aspects.
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 d7d8f54..797a3d2 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 3de9a3c..26e2a9b 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;
--
1.7.10.4
More information about the wine-patches
mailing list