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