diff --git a/server/async.c b/server/async.c
index 8307e20c0bcab879d2e09f99ddc212835942bfcc..26221a341e83fdbd0b95d53770ead35d524319eb 100644
--- a/server/async.c
+++ b/server/async.c
@@ -166,8 +166,7 @@ struct async_queue *create_async_queue( struct fd *fd )
 }
 
 /* create an async on a given queue of a fd */
-struct async *create_async( struct thread *thread, const struct timeval *timeout,
-                            struct async_queue *queue, const async_data_t *data )
+struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data )
 {
     struct event *event = NULL;
     struct async *async;
@@ -184,16 +183,23 @@ struct async *create_async( struct thread *thread, const struct timeval *timeout
     async->thread = (struct thread *)grab_object( thread );
     async->event = event;
     async->data = *data;
+    async->timeout = NULL;
 
     list_add_tail( &queue->queue, &async->queue_entry );
-
-    if (timeout) async->timeout = add_timeout_user( timeout, async_timeout, async );
-    else async->timeout = NULL;
+    grab_object( async );
 
     if (event) reset_event( event );
     return async;
 }
 
+/* set the timeout of an async operation */
+void async_set_timeout( struct async *async, const struct timeval *timeout )
+{
+    if (async->timeout) remove_timeout_user( async->timeout );
+    if (timeout) async->timeout = add_timeout_user( timeout, async_timeout, async );
+    else async->timeout = NULL;
+}
+
 /* store the result of the client-side async callback */
 void async_set_result( struct object *obj, unsigned int status )
 {
diff --git a/server/change.c b/server/change.c
index c4696a0a80f5e46e88d5f36fbe729b7241545fe0..30b7346dafe11f88282c8a6d535a07e58feb3e74 100644
--- a/server/change.c
+++ b/server/change.c
@@ -1058,6 +1058,7 @@ DECL_HANDLER(read_directory_changes)
 {
     struct event *event = NULL;
     struct dir *dir;
+    struct async *async;
 
     if (!req->filter)
     {
@@ -1079,7 +1080,7 @@ DECL_HANDLER(read_directory_changes)
     dir->event = event;
 
     /* requests don't timeout */
-    if (!fd_queue_async_timeout( dir->fd, &req->async, ASYNC_TYPE_WAIT, 0, NULL )) goto end;
+    if (!(async = fd_queue_async( dir->fd, &req->async, ASYNC_TYPE_WAIT, 0 ))) goto end;
 
     /* assign it once */
     if (!dir->filter)
@@ -1103,6 +1104,7 @@ DECL_HANDLER(read_directory_changes)
     if (!inotify_adjust_changes( dir ))
         dnotify_adjust_changes( dir );
 
+    release_object( async );
     set_error(STATUS_PENDING);
 
 end:
diff --git a/server/fd.c b/server/fd.c
index e8737017cef0a531c06f0a53e8680727e6d4b3b4..279f72ac5aedfc4afd27d85a190e3c366f14cd24 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1708,38 +1708,37 @@ void default_poll_event( struct fd *fd, int event )
     wake_up( fd->user, 0 );
 }
 
-int fd_queue_async_timeout( struct fd *fd, const async_data_t *data, int type, int count,
-                            const struct timeval *timeout )
+struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
 {
     struct async_queue *queue;
+    struct async *async;
 
     switch (type)
     {
     case ASYNC_TYPE_READ:
-        if (!fd->read_q && !(fd->read_q = create_async_queue( fd ))) return 0;
+        if (!fd->read_q && !(fd->read_q = create_async_queue( fd ))) return NULL;
         queue = fd->read_q;
         break;
     case ASYNC_TYPE_WRITE:
-        if (!fd->write_q && !(fd->write_q = create_async_queue( fd ))) return 0;
+        if (!fd->write_q && !(fd->write_q = create_async_queue( fd ))) return NULL;
         queue = fd->write_q;
         break;
     case ASYNC_TYPE_WAIT:
-        if (!fd->wait_q && !(fd->wait_q = create_async_queue( fd ))) return 0;
+        if (!fd->wait_q && !(fd->wait_q = create_async_queue( fd ))) return NULL;
         queue = fd->wait_q;
         break;
     default:
         assert(0);
     }
 
-    if (!create_async( current, timeout, queue, data )) return 0;
-    set_error( STATUS_PENDING );
-
-    if (!fd->inode)
-        set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
-    else  /* regular files are always ready for read and write */
-        if (type != ASYNC_TYPE_WAIT) async_wake_up( queue, STATUS_ALERTED );
-
-    return 1;
+    if ((async = create_async( current, queue, data )))
+    {
+        if (!fd->inode)
+            set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
+        else  /* regular files are always ready for read and write */
+            if (type != ASYNC_TYPE_WAIT) async_wake_up( queue, STATUS_ALERTED );
+    }
+    return async;
 }
 
 void fd_async_wake_up( struct fd *fd, int type, unsigned int status )
@@ -1763,6 +1762,7 @@ void fd_async_wake_up( struct fd *fd, int type, unsigned int status )
 void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
 {
     int flags;
+    struct async *async;
 
     fd->fd_ops->get_file_info( fd, &flags );
     if (!(flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)))
@@ -1770,7 +1770,11 @@ void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type,
         set_error( STATUS_INVALID_HANDLE );
         return;
     }
-    fd_queue_async_timeout( fd, data, type, count, NULL );
+    if ((async = fd_queue_async( fd, data, type, count )))
+    {
+        release_object( async );
+        set_error( STATUS_PENDING );
+    }
 }
 
 void default_fd_cancel_async( struct fd *fd )
diff --git a/server/file.h b/server/file.h
index 9bae11276a17780802f0b83e9bdc49316e85c229..ca2e42685f74475a7f79cd2c3e48220676b64b84 100644
--- a/server/file.h
+++ b/server/file.h
@@ -69,8 +69,7 @@ extern void default_fd_remove_queue( struct object *obj, struct wait_queue_entry
 extern int default_fd_signaled( struct object *obj, struct thread *thread );
 extern int default_fd_get_poll_events( struct fd *fd );
 extern void default_poll_event( struct fd *fd, int event );
-extern int fd_queue_async_timeout( struct fd *fd, const async_data_t *data, int type,
-                                   int count, const struct timeval *timeout );
+extern struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
 extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void default_fd_cancel_async( struct fd *fd );
@@ -125,8 +124,9 @@ extern struct object *create_serial( struct fd *fd, unsigned int options );
 
 /* async I/O functions */
 extern struct async_queue *create_async_queue( struct fd *fd );
-extern struct async *create_async( struct thread *thread, const struct timeval *timeout,
-                                   struct async_queue *queue, const async_data_t *data );
+extern struct async *create_async( struct thread *thread, struct async_queue *queue,
+                                   const async_data_t *data );
+extern void async_set_timeout( struct async *async, const struct timeval *timeout );
 extern void async_set_result( struct object *obj, unsigned int status );
 extern int async_waiting( struct async_queue *queue );
 extern void async_wake_up( struct async_queue *queue, unsigned int status );
diff --git a/server/mailslot.c b/server/mailslot.c
index d9716fe922330ee4c2a2719827c3ac592ba15ea7..227c99f4d23684b4348244eb2b5edfc1cdb5e4a2 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -282,6 +282,7 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces
 static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
 {
     struct mailslot *mailslot = get_fd_user( fd );
+    struct async *async;
 
     assert(mailslot->obj.ops == &mailslot_ops);
 
@@ -292,13 +293,17 @@ static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int t
         return;
     }
 
-    if (mailslot->read_timeout != -1)
+    if ((async = fd_queue_async( fd, data, type, count )))
     {
-        struct timeval when = current_time;
-        add_timeout( &when, max(1,mailslot->read_timeout) );
-        fd_queue_async_timeout( fd, data, type, count, &when );
+        if (mailslot->read_timeout != -1)
+        {
+            struct timeval when = current_time;
+            add_timeout( &when, max(1,mailslot->read_timeout) );
+            async_set_timeout( async, &when );
+        }
+        release_object( async );
+        set_error( STATUS_PENDING );
     }
-    else fd_queue_async_timeout( fd, data, type, count, NULL );
 }
 
 static void mailslot_device_dump( struct object *obj, int verbose )
diff --git a/server/named_pipe.c b/server/named_pipe.c
index d76c2420d164452d3b9eea40c53de2eb499d770e..6afcdb6bc2cdbeb485a261314117cb2456fdf2a9 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -793,6 +793,7 @@ DECL_HANDLER(create_named_pipe)
 DECL_HANDLER(connect_named_pipe)
 {
     struct pipe_server *server;
+    struct async *async;
 
     server = get_pipe_server_obj(current->process, req->handle, 0);
     if (!server)
@@ -804,9 +805,12 @@ DECL_HANDLER(connect_named_pipe)
     case ps_wait_connect:
         assert( !server->fd );
         server->state = ps_wait_open;
-        create_async( current, NULL, server->wait_q, &req->async );
-        if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS );
-        set_error( STATUS_PENDING );
+        if ((async = create_async( current, server->wait_q, &req->async )))
+        {
+            if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS );
+            release_object( async );
+            set_error( STATUS_PENDING );
+        }
         break;
     case ps_connected_server:
         assert( server->fd );
@@ -848,23 +852,25 @@ DECL_HANDLER(wait_named_pipe)
     server = find_available_server( pipe );
     if (!server)
     {
+        struct async *async;
+
         if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL )))
         {
             release_object( pipe );
             return;
         }
-        if (req->timeout == NMPWAIT_WAIT_FOREVER)
-        {
-            if (create_async( current, NULL, pipe->waiters, &req->async ))
-                set_error( STATUS_PENDING );
-        }
-        else
+
+        if ((async = create_async( current, pipe->waiters, &req->async )))
         {
-            struct timeval when = current_time;
-            if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
-            else add_timeout( &when, req->timeout );
-            if (create_async( current, &when, pipe->waiters, &req->async ))
-                set_error( STATUS_PENDING );
+            if (req->timeout != NMPWAIT_WAIT_FOREVER)
+            {
+                struct timeval when = current_time;
+                if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
+                else add_timeout( &when, req->timeout );
+                async_set_timeout( async, &when );
+            }
+            release_object( async );
+            set_error( STATUS_PENDING );
         }
     }
     else release_object( server );
diff --git a/server/serial.c b/server/serial.c
index 12401ac5177138671d612098bbf0e3cedfb3c88a..42a3f722f0e401f5f65fe9f286f36e14c4ef06e8 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -198,8 +198,8 @@ static enum server_fd_type serial_get_info( struct fd *fd, int *flags )
 static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
 {
     struct serial *serial = get_fd_user( fd );
-    struct timeval when = current_time;
     int timeout = 0;
+    struct async *async;
 
     assert(serial->obj.ops == &serial_ops);
 
@@ -213,8 +213,17 @@ static void serial_queue_async( struct fd *fd, const async_data_t *data, int typ
         break;
     }
 
-    add_timeout( &when, timeout );
-    fd_queue_async_timeout( fd, data, type, count, timeout ? &when : NULL );
+    if ((async = fd_queue_async( fd, data, type, count )))
+    {
+        if (timeout)
+        {
+            struct timeval when = current_time;
+            add_timeout( &when, timeout );
+            async_set_timeout( async, &when );
+        }
+        release_object( async );
+        set_error( STATUS_PENDING );
+    }
 }
 
 static void serial_flush( struct fd *fd, struct event **event )
diff --git a/server/sock.c b/server/sock.c
index b9938f7a016012ba78545171d62963e283406e02..1e70f2e197e885e1b4ce03f87b13ed4495f73eab 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -546,7 +546,9 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
     }
     else
     {
-        if (!create_async( current, NULL, queue, data )) return;
+        struct async *async;
+        if (!(async = create_async( current, queue, data ))) return;
+        release_object( async );
         set_error( STATUS_PENDING );
     }