Order of send message processing was not respected and the message
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/errno.h>
13 #include <sys/stat.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18
19 #include "winerror.h"
20 #include "winbase.h"
21 #include "server/thread.h"
22
23 enum side { READ_SIDE, WRITE_SIDE };
24
25 struct pipe
26 {
27     struct object obj;             /* object header */
28     struct pipe  *other;           /* the pipe other end */
29     int           fd;              /* Unix file descriptor */
30     enum side     side;            /* which side of the pipe is this */
31 };
32
33 static void pipe_dump( struct object *obj, int verbose );
34 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
35 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
36 static int pipe_signaled( struct object *obj, struct thread *thread );
37 static int pipe_get_read_fd( struct object *obj );
38 static int pipe_get_write_fd( struct object *obj );
39 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
40 static void pipe_destroy( struct object *obj );
41
42 static const struct object_ops pipe_ops =
43 {
44     pipe_dump,
45     pipe_add_queue,
46     pipe_remove_queue,
47     pipe_signaled,
48     no_satisfied,
49     pipe_get_read_fd,
50     pipe_get_write_fd,
51     no_flush,
52     pipe_get_info,
53     pipe_destroy
54 };
55
56 static const struct select_ops select_ops =
57 {
58     default_select_event,
59     NULL   /* we never set a timeout on a pipe */
60 };
61
62 int create_pipe( struct object *obj[2] )
63 {
64     struct pipe *newpipe[2];
65     int fd[2];
66
67     if (pipe( fd ) == -1)
68     {
69         file_set_error();
70         return 0;
71     }
72     if (!(newpipe[0] = mem_alloc( sizeof(struct pipe) )))
73     {
74         close( fd[0] );
75         close( fd[1] );
76         return 0;
77     }
78     if (!(newpipe[1] = mem_alloc( sizeof(struct pipe) )))
79     {
80         close( fd[0] );
81         close( fd[1] );
82         free( newpipe[0] );
83         return 0;
84     }
85     init_object( &newpipe[0]->obj, &pipe_ops, NULL );
86     init_object( &newpipe[1]->obj, &pipe_ops, NULL );
87     newpipe[0]->fd    = fd[0];
88     newpipe[0]->other = newpipe[1];
89     newpipe[0]->side  = READ_SIDE;
90     newpipe[1]->fd    = fd[1];
91     newpipe[1]->other = newpipe[0];
92     newpipe[1]->side  = WRITE_SIDE;
93     obj[0] = &newpipe[0]->obj;
94     obj[1] = &newpipe[1]->obj;
95     CLEAR_ERROR();
96     return 1;
97 }
98
99 static void pipe_dump( struct object *obj, int verbose )
100 {
101     struct pipe *pipe = (struct pipe *)obj;
102     assert( obj->ops == &pipe_ops );
103     fprintf( stderr, "Pipe %s-side fd=%d\n",
104              (pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
105 }
106
107 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
108 {
109     struct pipe *pipe = (struct pipe *)obj;
110     assert( obj->ops == &pipe_ops );
111     if (!obj->head)  /* first on the queue */
112     {
113         if (!add_select_user( pipe->fd,
114                               (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT,
115                               &select_ops, pipe ))
116         {
117             SET_ERROR( ERROR_OUTOFMEMORY );
118             return 0;
119         }
120     }
121     add_queue( obj, entry );
122     return 1;
123 }
124
125 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
126 {
127     struct pipe *pipe = (struct pipe *)grab_object(obj);
128     assert( obj->ops == &pipe_ops );
129
130     remove_queue( obj, entry );
131     if (!obj->head)  /* last on the queue is gone */
132         remove_select_user( pipe->fd );
133     release_object( obj );
134 }
135
136 static int pipe_signaled( struct object *obj, struct thread *thread )
137 {
138     struct pipe *pipe = (struct pipe *)obj;
139     struct timeval tv = { 0, 0 };
140     fd_set fds;
141
142     assert( obj->ops == &pipe_ops );
143     FD_ZERO( &fds );
144     FD_SET( pipe->fd, &fds );
145     if (pipe->side == READ_SIDE)
146         return select( pipe->fd + 1, &fds, NULL, NULL, &tv ) > 0;
147     else
148         return select( pipe->fd + 1, NULL, &fds, NULL, &tv ) > 0;
149 }
150
151 static int pipe_get_read_fd( struct object *obj )
152 {
153     struct pipe *pipe = (struct pipe *)obj;
154     assert( obj->ops == &pipe_ops );
155
156     if (!pipe->other)
157     {
158         SET_ERROR( ERROR_BROKEN_PIPE );
159         return -1;
160     }
161     if (pipe->side != READ_SIDE)  /* FIXME: should not be necessary */
162     {
163         SET_ERROR( ERROR_ACCESS_DENIED );
164         return -1;
165     }
166     return dup( pipe->fd );
167 }
168
169 static int pipe_get_write_fd( struct object *obj )
170 {
171     struct pipe *pipe = (struct pipe *)obj;
172     assert( obj->ops == &pipe_ops );
173
174     if (!pipe->other)
175     {
176         SET_ERROR( ERROR_BROKEN_PIPE );
177         return -1;
178     }
179     if (pipe->side != WRITE_SIDE)  /* FIXME: should not be necessary */
180     {
181         SET_ERROR( ERROR_ACCESS_DENIED );
182         return -1;
183     }
184     return dup( pipe->fd );
185 }
186
187 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
188 {
189     memset( reply, 0, sizeof(*reply) );
190     reply->type = FILE_TYPE_PIPE;
191     return 1;
192 }
193
194 static void pipe_destroy( struct object *obj )
195 {
196     struct pipe *pipe = (struct pipe *)obj;
197     assert( obj->ops == &pipe_ops );
198
199     if (pipe->other) pipe->other->other = NULL;
200     close( pipe->fd );
201     free( pipe );
202 }