about summary refs log tree commit diff
path: root/sysdeps/pthread
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-10-29 21:01:24 -0700
committerUlrich Drepper <drepper@redhat.com>2009-10-29 21:01:24 -0700
commit584715c3a9b0030729e0a8504c820b3bd8d9353d (patch)
tree9097c35972e90dbcc544567c5b3c705cb0d85e74 /sysdeps/pthread
parentc240c3a58f21d72982e74a485bd7c4900f188876 (diff)
downloadglibc-584715c3a9b0030729e0a8504c820b3bd8d9353d.tar.gz
glibc-584715c3a9b0030729e0a8504c820b3bd8d9353d.tar.xz
glibc-584715c3a9b0030729e0a8504c820b3bd8d9353d.zip
Fix AIO when thread creation failed.
Several bugs fixed when we needed to create a thread to work on AIO
requests but failed and there is not one running.
Diffstat (limited to 'sysdeps/pthread')
-rw-r--r--sysdeps/pthread/aio_misc.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/sysdeps/pthread/aio_misc.c b/sysdeps/pthread/aio_misc.c
index fd3fcbb755..c82acbbc2d 100644
--- a/sysdeps/pthread/aio_misc.c
+++ b/sysdeps/pthread/aio_misc.c
@@ -1,5 +1,5 @@
 /* Handle general operations.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -372,9 +372,13 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 
       /* Simply enqueue it after the running one according to the
 	 priority.  */
+      last = NULL;
       while (runp->next_prio != NULL
 	     && runp->next_prio->aiocbp->aiocb.__abs_prio >= prio)
-	runp = runp->next_prio;
+	{
+	  last = runp;
+	  runp = runp->next_prio;
+	}
 
       newp->next_prio = runp->next_prio;
       runp->next_prio = newp;
@@ -403,6 +407,7 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 	}
 
       newp->next_prio = NULL;
+      last = NULL;
     }
 
   if (running == yes)
@@ -423,7 +428,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 	  running = newp->running = allocated;
 
 	  /* Now try to start a thread.  */
-	  if (aio_create_helper_thread (&thid, handle_fildes_io, newp) == 0)
+	  result = aio_create_helper_thread (&thid, handle_fildes_io, newp);
+	  if (result == 0)
 	    /* We managed to enqueue the request.  All errors which can
 	       happen now can be recognized by calls to `aio_return' and
 	       `aio_error'.  */
@@ -434,10 +440,14 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 	      running = newp->running = yes;
 
 	      if (nthreads == 0)
-		/* We cannot create a thread in the moment and there is
-		   also no thread running.  This is a problem.  `errno' is
-		   set to EAGAIN if this is only a temporary problem.  */
-		result = -1;
+		{
+		  /* We cannot create a thread in the moment and there is
+		     also no thread running.  This is a problem.  `errno' is
+		     set to EAGAIN if this is only a temporary problem.  */
+		  __aio_remove_request (last, newp, 0);
+		}
+	      else
+		result = 0;
 	    }
 	}
     }
@@ -459,6 +469,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
     {
       /* Something went wrong.  */
       __aio_free_request (newp);
+      aiocbp->aiocb.__error_code = result;
+      __set_errno (result);
       newp = NULL;
     }