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
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) {