Named Pipe patch

Dan Kegel dank at kegel.com
Sun Mar 9 17:14:06 CST 2003


Mike McCormack wrote:
> This patch probably shouldn't be applied... it's just to let everybody 
> know where I'm at with the named pipes code.
> 
> The patch moves away from using unix pipes to implement named pipes, and 
> instead implements pipes internally. This is necessary to implement 
> message mode properly (without race conditions).

Since Mike's patch is a big rearchitecting that Alexander isn't
totally comfortable with, how about something along these lines
as a first step?  To reflect the fact that freshly minted named
pipes can be connected to, I added an fd_for_peer variable
that is only set when a named pipe is first created, and
added a new state 'ps_fresh_server' to mark pipes which have
been freshly created, and arranged for find_partner to be
able to find partners in multiple states.

I didn't bother dealing with refcounting of the fd_for_peer variable
that holds the file descriptor.

I'm going on a net diet, so this is the last you'll
hear from me for a while.  When I get back I hope this is all sorted out :-)
- Dan

-- 
Dan Kegel
http://www.kegel.com
http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045
-------------- next part --------------
Index: server/named_pipe.c
===================================================================
RCS file: /home/wine/wine/server/named_pipe.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 named_pipe.c
--- server/named_pipe.c	19 Feb 2003 00:33:33 -0000	1.20
+++ server/named_pipe.c	9 Mar 2003 23:08:22 -0000
@@ -47,13 +47,14 @@
 
 enum pipe_state
 {
-    ps_none,
-    ps_idle_server,
-    ps_wait_open,
-    ps_wait_connect,
-    ps_connected_server,
-    ps_connected_client,
-    ps_disconnected
+    ps_none = 0,
+    ps_idle_server = 1,			/* after disconnect */
+    ps_wait_open = 2,
+    ps_wait_connect = 4,
+    ps_connected_server = 8,
+    ps_connected_client = 16,
+    ps_disconnected = 32,
+    ps_fresh_server = 64,		/* after create but before first connection */
 };
 
 struct named_pipe;
@@ -62,6 +63,7 @@ struct pipe_user
 {
     struct object       obj;
     struct fd          *fd;
+    int                 fd_for_peer;	/* used only in fresh state */
     enum pipe_state     state;
     struct pipe_user   *other;
     struct named_pipe  *pipe;
@@ -273,6 +275,7 @@ static struct pipe_user *create_pipe_use
         return NULL;
 
     user->fd = NULL;
+    user->fd_for_peer = -1;
     user->pipe = pipe;
     user->state = ps_none;
     user->other = NULL;
@@ -290,13 +293,13 @@ static struct pipe_user *create_pipe_use
     return user;
 }
 
-static struct pipe_user *find_partner(struct named_pipe *pipe, enum pipe_state state)
+static struct pipe_user *find_partner(struct named_pipe *pipe, int states)
 {
     struct pipe_user *x;
 
     for(x = pipe->users; x; x=x->next)
     {
-        if(x->state==state)
+        if(x->state & states)
         break;
     }
 
@@ -329,7 +332,13 @@ DECL_HANDLER(create_named_pipe)
 
     if(user)
     {
-        user->state = ps_idle_server;
+        int fds[2];
+        user->state = ps_fresh_server;
+        if (!socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
+        {
+            user->fd = alloc_fd( &pipe_user_fd_ops, fds[1], &user->obj );
+            user->fd_for_peer = fds[0];
+        }
         reply->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
         release_object( user );
     }
@@ -349,7 +358,7 @@ DECL_HANDLER(open_named_pipe)
         set_error( STATUS_NO_SUCH_FILE );
         return;
     }
-    if (!(partner = find_partner(pipe, ps_wait_open)))
+    if (!(partner = find_partner(pipe, ps_wait_open | ps_fresh_server)))
     {
         release_object(pipe);
         set_error( STATUS_PIPE_NOT_AVAILABLE );
@@ -359,21 +368,31 @@ DECL_HANDLER(open_named_pipe)
     {
         int fds[2];
 
-        if(!socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
-        {
-            user->fd = alloc_fd( &pipe_user_fd_ops, fds[1], &user->obj );
-            partner->fd = alloc_fd( &pipe_user_fd_ops, fds[0], &partner->obj );
-            if (user->fd && partner->fd)
+        if (partner->state == ps_fresh_server ) {
+            user->fd = alloc_fd( &pipe_user_fd_ops, partner->fd_for_peer, &user->obj );
+            partner->fd_for_peer = -1;
+            partner->state = ps_connected_server;
+            partner->other = user;
+            user->state = ps_connected_client;
+            user->other = partner;
+            reply->handle = alloc_handle( current->process, user, req->access, 0 );
+        } else if (partner->state == ps_fresh_server ) {
+            if (!socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
             {
-                notify_waiter(partner,STATUS_SUCCESS);
-                partner->state = ps_connected_server;
-                partner->other = user;
-                user->state = ps_connected_client;
-                user->other = partner;
-                reply->handle = alloc_handle( current->process, user, req->access, 0 );
+                user->fd = alloc_fd( &pipe_user_fd_ops, fds[1], &user->obj );
+                partner->fd = alloc_fd( &pipe_user_fd_ops, fds[0], &partner->obj );
+                if (user->fd && partner->fd)
+                {
+                    notify_waiter(partner,STATUS_SUCCESS);
+                    partner->state = ps_connected_server;
+                    partner->other = user;
+                    user->state = ps_connected_client;
+                    user->other = partner;
+                    reply->handle = alloc_handle( current->process, user, req->access, 0 );
+                }
             }
+            else file_set_error();
         }
-        else file_set_error();
 
         release_object( user );
     }
@@ -389,7 +408,7 @@ DECL_HANDLER(connect_named_pipe)
     if(!user)
         return;
 
-    if( user->state != ps_idle_server )
+    if( (user->state & (ps_idle_server|ps_fresh_server)) == 0 )
     {
         set_error(STATUS_PORT_ALREADY_SET);
     }
Index: dlls/kernel/tests/pipe.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/pipe.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 pipe.c
--- dlls/kernel/tests/pipe.c	25 Feb 2003 03:56:43 -0000	1.2
+++ dlls/kernel/tests/pipe.c	9 Mar 2003 23:08:22 -0000
@@ -88,10 +88,7 @@ void test_CreateNamedPipeA(void)
 
     hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
             NULL, OPEN_EXISTING, 0, 0);
-    todo_wine
-    {
-        ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
-    }
+	ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
 
     /* don't try to do i/o if one side couldn't be opened, as it hangs */
     if (hFile != INVALID_HANDLE_VALUE) {


More information about the wine-patches mailing list