Alexandre Julliard : services: Add a timeout to all pipe communications with the service process.
Alexandre Julliard
julliard at winehq.org
Fri May 20 12:44:31 CDT 2011
Module: wine
Branch: master
Commit: f51668fdf9dad4e40194f7e08e44743c1c1c1388
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f51668fdf9dad4e40194f7e08e44743c1c1c1388
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri May 20 12:31:27 2011 +0200
services: Add a timeout to all pipe communications with the service process.
---
programs/services/rpc.c | 16 ++++++++++++++--
programs/services/services.c | 36 ++++++++++++++++++++++++++++--------
programs/services/services.h | 1 +
3 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index d1dd39e..15ea7cf 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -893,16 +893,28 @@ static BOOL service_accepts_control(const struct service_entry *service, DWORD d
BOOL service_send_command( struct service_entry *service, HANDLE pipe,
const void *data, DWORD size, DWORD *result )
{
+ OVERLAPPED overlapped;
DWORD count;
BOOL r;
- r = WriteFile(pipe, data, size, &count, NULL);
+ overlapped.hEvent = service->overlapped_event;
+ r = WriteFile(pipe, data, size, &count, &overlapped);
+ if (!r && GetLastError() == ERROR_IO_PENDING)
+ {
+ WaitForSingleObject( service->overlapped_event, service_pipe_timeout );
+ r = GetOverlappedResult( pipe, &overlapped, &count, FALSE );
+ }
if (!r || count != size)
{
WINE_ERR("service protocol error - failed to write pipe!\n");
return FALSE;
}
- r = ReadFile(pipe, result, sizeof *result, &count, NULL);
+ r = ReadFile(pipe, result, sizeof *result, &count, &overlapped);
+ if (!r && GetLastError() == ERROR_IO_PENDING)
+ {
+ WaitForSingleObject( service->overlapped_event, service_pipe_timeout );
+ r = GetOverlappedResult( pipe, &overlapped, &count, FALSE );
+ }
if (!r || count != sizeof *result)
{
WINE_ERR("service protocol error - failed to read pipe "
diff --git a/programs/services/services.c b/programs/services/services.c
index 2b1b8c5..35edbba 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -95,6 +95,7 @@ void free_service_entry(struct service_entry *entry)
HeapFree(GetProcessHeap(), 0, entry->dependOnGroups);
CloseHandle(entry->control_mutex);
CloseHandle(entry->control_pipe);
+ CloseHandle(entry->overlapped_event);
CloseHandle(entry->status_changed_event);
HeapFree(GetProcessHeap(), 0, entry);
}
@@ -672,8 +673,10 @@ static DWORD service_wait_for_startup(struct service_entry *service_entry, HANDL
/******************************************************************************
* service_send_start_message
*/
-static BOOL service_send_start_message(struct service_entry *service, LPCWSTR *argv, DWORD argc)
+static BOOL service_send_start_message(struct service_entry *service, HANDLE process_handle,
+ LPCWSTR *argv, DWORD argc)
{
+ OVERLAPPED overlapped;
DWORD i, len, result;
service_start_info *ssi;
LPWSTR p;
@@ -681,12 +684,27 @@ static BOOL service_send_start_message(struct service_entry *service, LPCWSTR *a
WINE_TRACE("%s %p %d\n", wine_dbgstr_w(service->name), argv, argc);
- /* FIXME: this can block so should be done in another thread */
- r = ConnectNamedPipe(service->control_pipe, NULL);
- if (!r && GetLastError() != ERROR_PIPE_CONNECTED)
+ overlapped.hEvent = service->overlapped_event;
+ if (!ConnectNamedPipe(service->control_pipe, &overlapped))
{
- WINE_ERR("pipe connect failed\n");
- return FALSE;
+ if (GetLastError() == ERROR_IO_PENDING)
+ {
+ HANDLE handles[2];
+ handles[0] = service->overlapped_event;
+ handles[1] = process_handle;
+ if (WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout ) != WAIT_OBJECT_0)
+ CancelIo( service->control_pipe );
+ if (!HasOverlappedCompleted( &overlapped ))
+ {
+ WINE_ERR( "service %s failed to start\n", wine_dbgstr_w( service->name ));
+ return FALSE;
+ }
+ }
+ else if (GetLastError() != ERROR_PIPE_CONNECTED)
+ {
+ WINE_ERR("pipe connect failed\n");
+ return FALSE;
+ }
}
/* calculate how much space do we need to send the startup info */
@@ -743,9 +761,11 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
if (!service->status_changed_event)
service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ if (!service->overlapped_event)
+ service->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
name = service_get_pipe_name();
- service->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX,
+ service->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL );
HeapFree(GetProcessHeap(), 0, name);
if (service->control_pipe==INVALID_HANDLE_VALUE)
@@ -760,7 +780,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
if (err == ERROR_SUCCESS)
{
- if (!service_send_start_message(service, service_argv, service_argc))
+ if (!service_send_start_message(service, process_handle, service_argv, service_argc))
err = ERROR_SERVICE_REQUEST_TIMEOUT;
}
diff --git a/programs/services/services.h b/programs/services/services.h
index 63154c8..448ddfa 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -44,6 +44,7 @@ struct service_entry
LPWSTR dependOnGroups;
HANDLE control_mutex;
HANDLE control_pipe;
+ HANDLE overlapped_event;
HANDLE status_changed_event;
};
More information about the wine-cvs
mailing list