Add missing release object so server exits cleanly.
[wine.git] / server / async.c
blob2d37b836084f1fa57e0d338877d0b1ad42b8d7b6
1 /*
2 * Server-side support for async i/o operations
4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2000 Mike McCormack
7 * TODO:
8 * Fix up WaitCommEvent operations. Currently only EV_RXCHAR is supported.
9 * This may require modifications to the linux kernel to enable select
10 * to wait on Modem Status Register deltas. (delta DCD, CTS, DSR or RING)
14 #include "config.h"
16 #include <assert.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #ifdef HAVE_SYS_ERRNO_H
23 #include <sys/errno.h>
24 #endif
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <utime.h>
31 #include <termios.h>
32 #include <sys/ioctl.h>
34 #include "winerror.h"
35 #include "winbase.h"
37 #include "handle.h"
38 #include "thread.h"
39 #include "request.h"
41 struct async
43 struct object obj;
44 void *client_overlapped;
45 int type;
46 int result;
47 int count;
48 int eventmask;
49 struct async *next;
50 struct timeval tv;
51 struct timeout_user *timeout;
52 struct wait_queue_entry wait;
53 void *buffer;
54 void *func;
55 struct thread *thread;
56 struct object *file;
59 static void async_dump( struct object *obj, int verbose );
60 static void async_destroy( struct object *obj );
61 static int async_get_poll_events( struct object *obj );
62 static int async_get_fd( struct object *obj );
63 static int async_get_info( struct object *obj, struct get_file_info_request *req );
64 static void async_poll_event( struct object *obj, int event );
65 static void overlapped_timeout (void *private);
67 static const struct object_ops async_ops =
69 sizeof(struct async), /* size */
70 async_dump, /* dump */
71 default_poll_add_queue, /* add_queue */
72 default_poll_remove_queue, /* remove_queue */
73 default_poll_signaled, /* signaled */
74 no_satisfied, /* satisfied */
75 async_get_poll_events, /* get_poll_events */
76 async_poll_event, /* poll_event */
77 async_get_fd, /* get_fd */
78 no_flush, /* flush */
79 async_get_info, /* get_file_info */
80 async_destroy /* destroy */
83 static void async_dump( struct object *obj, int verbose )
85 struct async *ov = (struct async *)obj;
87 assert( obj->ops == &async_ops );
89 fprintf( stderr, "async: overlapped %p %s\n",
90 ov->client_overlapped, ov->timeout?"with timeout":"");
93 /* same as file_destroy, but don't delete comm ports */
94 static void async_destroy( struct object *obj )
96 struct async *ov = (struct async *)obj;
97 assert( obj->ops == &async_ops );
99 if(ov->timeout)
101 remove_timeout_user(ov->timeout);
102 ov->timeout = NULL;
106 struct async *get_async_obj( struct process *process, handle_t handle, unsigned int access )
108 return (struct async *)get_handle_obj( process, handle, access, &async_ops );
111 static int async_get_poll_events( struct object *obj )
113 struct async *ov = (struct async *)obj;
114 assert( obj->ops == &async_ops );
116 /* FIXME: this should be a function pointer */
117 return serial_async_get_poll_events(ov);
120 static int async_get_fd( struct object *obj )
122 struct async *async = (struct async *)obj;
123 assert( obj->ops == &async_ops );
124 return async->obj.fd;
127 static int async_get_info( struct object *obj, struct get_file_info_request *req ) {
128 assert( obj->ops == &async_ops );
129 req->type = FILE_TYPE_CHAR;
130 req->attr = 0;
131 req->access_time = 0;
132 req->write_time = 0;
133 req->size_high = 0;
134 req->size_low = 0;
135 req->links = 0;
136 req->index_high = 0;
137 req->index_low = 0;
138 req->serial = 0;
139 return 1;
142 /* data access functions */
143 int async_type(struct async *ov)
145 return ov->type;
148 int async_count(struct async *ov)
150 return ov->count;
153 int async_get_eventmask(struct async *ov)
155 return ov->eventmask;
158 int async_set_eventmask(struct async *ov, int eventmask)
160 return ov->eventmask = eventmask;
163 DECL_HANDLER(create_async)
165 struct object *obj;
166 struct async *ov = NULL;
167 int fd;
169 req->ov_handle = 0;
170 if (!(obj = get_handle_obj( current->process, req->file_handle, 0, NULL)) )
171 return;
173 fd = dup(obj->fd);
174 if(fd<0)
176 release_object(obj);
177 set_error(STATUS_UNSUCCESSFUL);
178 return;
181 if(0>fcntl(fd, F_SETFL, O_NONBLOCK))
183 release_object(obj);
184 set_error(STATUS_UNSUCCESSFUL);
185 return;
188 ov = alloc_object (&async_ops, fd);
189 if(!ov)
191 release_object(obj);
192 set_error(STATUS_UNSUCCESSFUL);
193 return;
196 ov->client_overlapped = req->overlapped;
197 ov->next = NULL;
198 ov->timeout = NULL;
199 ov->type = req->type;
200 ov->thread = current;
201 ov->func = req->func;
202 ov->file = obj;
203 ov->buffer = req->buffer;
204 ov->count = req->count;
205 ov->tv.tv_sec = 0;
206 ov->tv.tv_usec = 0;
208 /* FIXME: this should be a function pointer */
209 serial_async_setup(obj,ov);
211 if( ov->tv.tv_sec || ov->tv.tv_usec )
213 ov->timeout = add_timeout_user(&ov->tv, overlapped_timeout, ov);
216 ov->obj.ops->add_queue(&ov->obj,&ov->wait);
218 req->ov_handle = alloc_handle( current->process, ov, GENERIC_READ|GENERIC_WRITE, 0 );
220 release_object(ov);
221 release_object(obj);
224 /* handler for async poll() events */
225 static void async_poll_event( struct object *obj, int event )
227 struct async *ov = (struct async *) obj;
229 /* queue an APC in the client thread to do our dirty work */
230 ov->obj.ops->remove_queue(&ov->obj,&ov->wait);
231 if(ov->timeout)
233 remove_timeout_user(ov->timeout);
234 ov->timeout = NULL;
237 /* FIXME: this should be a function pointer */
238 event = serial_async_poll_event(obj,event);
240 thread_queue_apc(ov->thread, NULL, ov->func, APC_ASYNC, 1, 3,
241 ov->client_overlapped, ov->buffer, event);
244 /* handler for async i/o timeouts */
245 static void overlapped_timeout (void *private)
247 struct async *ov = (struct async *) private;
249 ov->obj.ops->remove_queue(&ov->obj,&ov->wait);
250 ov->timeout = NULL;
252 thread_queue_apc(ov->thread, NULL, ov->func, APC_ASYNC, 1, 3,
253 ov->client_overlapped,ov->buffer, 0);
256 void async_add_timeout(struct async *ov, int timeout)
258 if(timeout)
260 gettimeofday(&ov->tv,0);
261 add_timeout(&ov->tv,timeout);
265 DECL_HANDLER(async_result)
267 struct async *ov;
269 if ((ov = get_async_obj( current->process, req->ov_handle, 0 )))
271 ov->result = req->result;
272 if(ov->result == STATUS_PENDING)
274 ov->obj.ops->add_queue(&ov->obj,&ov->wait);
275 if( (ov->tv.tv_sec || ov->tv.tv_usec) && !ov->timeout)
277 ov->timeout = add_timeout_user(&ov->tv, overlapped_timeout, ov);
280 release_object( ov );