[PATCH 1/2] server: Store async list in process object and use that to find async in cansel_async request.

Jacek Caban jacek at codeweavers.com
Thu Dec 1 05:09:10 CST 2016


On 30.11.2016 16:27, Alexandre Julliard wrote:
> Jacek Caban <jacek at codeweavers.com> writes:
>
>> @@ -614,6 +615,7 @@ static void process_destroy( struct object *obj )
>>  
>>      /* we can't have a thread remaining */
>>      assert( list_empty( &process->thread_list ));
>> +    assert( list_empty( &process->asyncs ));
> I don't think that this is guaranteed, I believe that there can still be
> asyncs in the queues of shared files.

I think it is guaranteed. async object holds thread reference and thread
object holds process reference, so process object will not be destroyed
until all its asyncs are released. Asyncs in queues of shared objects
will keep process object alive (and they shouldn't), but it's not new
with my patch. Am I missing something?

> We'd probably need to clear them explicitly at process exit.


I agree that we should. I will send a new series implementing that. I
tested that with the attached patch (I can't send it to wine-patches yet
because it uses pipes in message mode).


Thanks,

Jacek

-------------- next part --------------
commit 24fd85eade01d03cff3391be5a3f82bec246f97c
Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Dec 1 11:27:10 2016 +0100

    kernel32/tests: Added test of async write terminated by process exit.

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index cb2ca30..c17d2a0 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2801,8 +2801,37 @@ static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL
     test_flush_done(flush_thread);
 }
 
+static void child_process_write_pipe(HANDLE pipe)
+{
+    OVERLAPPED overlapped;
+    char buf[10000];
+
+    memset(buf, 'x', sizeof(buf));
+    overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
+
+    /* sleep until parent process tesrminates this process. */
+    Sleep(INFINITE);
+}
+
+static HANDLE create_writepipe_process(HANDLE pipe)
+{
+    STARTUPINFOA si = { sizeof(si) };
+    PROCESS_INFORMATION info;
+    char **argv, buf[MAX_PATH];
+    BOOL res;
+
+    winetest_get_mainargs(&argv);
+    sprintf(buf, "\"%s\" pipe writepipe %lx", argv[0], (UINT_PTR)pipe);
+    res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
+    ok(res, "CreateProcess failed: %u\n", GetLastError());
+    CloseHandle(info.hThread);
+
+    return info.hProcess;
+}
+
 static void create_overlapped_pipe(DWORD read_mode, HANDLE *client, HANDLE *server)
 {
+    SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
     DWORD mode = read_mode;
     OVERLAPPED overlapped;
     BOOL res;
@@ -2819,7 +2848,7 @@ static void create_overlapped_pipe(DWORD read_mode, HANDLE *client, HANDLE *serv
     test_not_signaled(*server);
     test_not_signaled(overlapped.hEvent);
 
-    *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     ok(*server != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
 
     res = SetNamedPipeHandleState(*client, &mode, NULL, NULL);
@@ -2834,6 +2863,8 @@ static void test_overlapped_transport(DWORD read_mode)
 {
     OVERLAPPED overlapped, overlapped2;
     HANDLE server, client, flush;
+    DWORD read_bytes;
+    HANDLE process;
     char buf[60000];
     BOOL res;
 
@@ -2877,10 +2908,32 @@ static void test_overlapped_transport(DWORD read_mode)
     test_flush_done(flush);
     CloseHandle(server);
     CloseHandle(client);
+
+    /* terminate process with pending write */
+    create_overlapped_pipe(read_mode, &client, &server);
+    process = create_writepipe_process(client);
+    /* succesfully read part of write that is pending in child process */
+    res = ReadFile(server, buf, 10, &read_bytes, NULL);
+    if(read_mode == PIPE_READMODE_BYTE)
+        ok(res, "ReadFile failed: %u\n", GetLastError());
+    else
+        ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError());
+    ok(read_bytes == 10, "read_bytes = %u\n", read_bytes);
+    TerminateProcess(process, 0);
+    winetest_wait_child_process(process);
+    /* after terminating process, there is no pending write and pipe buffer is empty */
+    overlapped_read_async(server, buf, 10, &overlapped);
+    overlapped_write_sync(client, buf, 1);
+    test_overlapped_result(server, &overlapped, 1, FALSE);
+    CloseHandle(process);
+    CloseHandle(server);
+    CloseHandle(client);
 }
 
 START_TEST(pipe)
 {
+    char **argv;
+    int argc;
     HMODULE hmod;
 
     hmod = GetModuleHandleA("advapi32.dll");
@@ -2889,6 +2942,16 @@ START_TEST(pipe)
     pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
     pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
 
+    argc = winetest_get_mainargs(&argv);
+
+    if (argc > 3 && !strcmp(argv[2], "writepipe"))
+    {
+        UINT_PTR handle;
+        sscanf(argv[3], "%lx", &handle);
+        child_process_write_pipe((HANDLE)handle);
+        return;
+    }
+
     if (test_DisconnectNamedPipe())
         return;
     test_CreateNamedPipe_instances_must_match();


More information about the wine-devel mailing list