2002-01-22 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / wait.c
index a830c2d..b86ca5f 100644 (file)
@@ -54,7 +54,7 @@ struct proc_s {
     int pid;
     GpgmeCtx ctx;
     struct wait_item_s *handler_list;
-    int ready;
+    int done;
 };
 
 struct wait_item_s {
@@ -63,7 +63,7 @@ struct wait_item_s {
     void *handler_value;
     int inbound;       /* this is an inbound data handler fd */
     struct proc_s *proc; /* backlink */
-    int ready;
+    int done;
     int frozen; /* copy of the frozen flag from the fd_table */
 };
 
@@ -75,61 +75,67 @@ static void run_idle (void);
 
 /* only to be called with a locked proc_queue */
 static int
-count_running_fds ( struct proc_s *proc )
+count_running_fds (struct proc_s *proc)
 {
-    struct wait_item_s *q;
-    int count = 0;
+  struct wait_item_s *q;
+  int count = 0;
 
-    for (q=proc->handler_list; q; q=q->next) {
-        if ( !q->frozen && !q->ready )
-            count++;
+  for (q = proc->handler_list; q; q=q->next)
+    {
+      if (!q->frozen && !q->done)
+       count++;
     }
-    return count;
+  return count;
 }
 
 /* only to be called with a locked proc_queue */
 static void
-set_process_ready ( struct proc_s *proc )
+set_process_done (struct proc_s *proc)
 {
-    struct wait_item_s *q, *q2;
-    int i;
-
-    assert (proc);
-    DEBUG2 ("set_process_ready(%p) pid=%d", proc, proc->pid );
-    LOCK (fd_table_lock);
-    for (q = proc->handler_list; q; q=q2) {
-        q2 = q->next;
-        for (i=0; i < fd_table_size; i++ ) {
-            if (fd_table[i].fd != -1 && q == fd_table[i].opaque ) {
-                fd_table[i].opaque = NULL;
-                fd_table[i].fd = -1;
+  struct wait_item_s *q, *q2;
+  int i;
+
+  assert (proc);
+  DEBUG2 ("set_process_done(%p) pid=%d", proc, proc->pid);
+  LOCK (fd_table_lock);
+  for (q = proc->handler_list; q; q=q2)
+    {
+      q2 = q->next;
+      for (i = 0; i < fd_table_size; i++)
+       {
+         if (fd_table[i].fd != -1 && q == fd_table[i].opaque)
+           {
+             fd_table[i].opaque = NULL;
+             fd_table[i].fd = -1;
             }
         }
-        xfree (q);
+      xfree (q);
     }
-    UNLOCK (fd_table_lock);
-    proc->handler_list = NULL;
-    proc->ready = 1;
+  UNLOCK (fd_table_lock);
+  proc->handler_list = NULL;
+  proc->done = 1;
 }
 
 void
-_gpgme_remove_proc_from_wait_queue ( int pid )
+_gpgme_remove_proc_from_wait_queue (int pid)
 {
     struct proc_s *proc, *last;
 
-    DEBUG1 ("removing process %d", pid );
+    DEBUG1 ("removing process %d", pid);
     LOCK (proc_queue_lock);
-    for (last=NULL, proc=proc_queue; proc; last = proc, proc = proc->next ) {
-        if (proc->pid == pid ) {
-            set_process_ready (proc);
+    for (last = NULL, proc = proc_queue; proc; last = proc, proc = proc->next)
+      {
+        if (proc->pid == pid)
+         {
+            set_process_done (proc);
             if (!last) 
-                proc_queue = proc->next;
+             proc_queue = proc->next;
             else 
-                last->next = proc->next;
+             last->next = proc->next;
             xfree (proc);
             break;
-        }
-    }
+         }
+      }
     UNLOCK (proc_queue_lock);
 }
 
@@ -148,49 +154,58 @@ _gpgme_remove_proc_from_wait_queue ( int pid )
  *  and no (or the given) request has finished.
  **/
 GpgmeCtx 
-gpgme_wait ( GpgmeCtx c, int hang ) 
+gpgme_wait (GpgmeCtx ctx, int hang)
 {
-    return _gpgme_wait_on_condition ( c, hang, NULL );
+  return _gpgme_wait_on_condition (ctx, hang, NULL);
 }
 
 GpgmeCtx 
-_gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond )
+_gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond)
 {
-    DEBUG3 ("waiting... ctx=%p hang=%d cond=%p", c, hang, cond );
-    do {
-        int any = 0;
-        struct proc_s *proc;
-
-        do_select();
-
-        if ( cond && *cond )
-            hang = 0;
-        else {
-            LOCK (proc_queue_lock);
-            for (proc=proc_queue; proc; proc = proc->next ) {
-                if ( !proc->ready && !count_running_fds (proc) ) {
-                    set_process_ready (proc);
-                }
-                if (c && proc->ready && proc->ctx == c)
-                    hang = 0;
-                if ( !proc->ready )
-                    any = 1;
+  DEBUG3 ("waiting... ctx=%p hang=%d cond=%p", ctx, hang, cond);
+  do
+    {
+      int any = 0;
+      struct proc_s *proc;
+
+      do_select ();
+
+      if (cond && *cond)
+       hang = 0;
+      else
+       {
+         LOCK (proc_queue_lock);
+         for (proc = proc_queue; proc; proc = proc->next)
+           {
+             if (!proc->done && !count_running_fds (proc))
+               set_process_done (proc);
+             if (ctx && proc->done && proc->ctx == ctx)
+               {
+                 hang = 0;
+                 ctx->pending = 0;
+               }
+                if (!proc->done)
+                 any = 1;
             }
-            UNLOCK (proc_queue_lock);
-            if (!any)
-                hang = 0;
+         UNLOCK (proc_queue_lock);
+         if (!any)
+           hang = 0;
         }
-        /* fixme: we should check here for hanging processes */
+      /* fixme: We should check here for hanging processes.  */
 
-        if (hang)
-            run_idle ();
-    } while (hang && !c->cancel );
-    c->cancel = 0; /* fixme: fix all functions, to return a cancel error */
-    return c;
+      if (hang)
+       run_idle ();
+    }
+  while (hang && !ctx->cancel);
+  if (ctx->cancel)
+    {
+      ctx->cancel = 0;  /* fixme: Fix all functions to return a cancel error.  */
+      ctx->pending = 0;
+    }
+  return ctx;
 }
 
 
-
 /*
  * We use this function to do the select stuff for all running
  * gpgs.  A future version might provide a facility to delegate
@@ -201,168 +216,182 @@ _gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond )
  */
 
 static int
-do_select ( void )
+do_select (void)
 {
-    int i, n;
-    int any=0;
+  int i, n;
+  int any = 0;
     
-    n = _gpgme_io_select ( fd_table, fd_table_size );
-    if ( n <= 0 ) 
-        return 0; /* error or timeout */
-
-    for (i=0; i < fd_table_size && n; i++ ) {
-        if ( fd_table[i].fd != -1 && fd_table[i].signaled 
-             && !fd_table[i].frozen ) {
-            struct wait_item_s *q;
-
-            assert (n);
-            n--;
+  n = _gpgme_io_select (fd_table, fd_table_size);
+  if (n <= 0) 
+    return 0; /* error or timeout */
+
+  for (i = 0; i < fd_table_size && n; i++)
+    {
+      if (fd_table[i].fd != -1 && fd_table[i].signaled 
+         && !fd_table[i].frozen)
+       {
+         struct wait_item_s *q;
+
+         assert (n);
+         n--;
             
-            q = fd_table[i].opaque;
-            assert ( q );
-            assert ( q->proc );
-            assert ( !q->ready );
-            any = 1;
-            if ( q->handler (q->handler_value,
-                             q->proc->pid, fd_table[i].fd ) ) {
-                DEBUG2 ("setting fd %d (q=%p) ready", fd_table[i].fd, q );
-                q->ready = 1;
-                /* free the table entry*/
-                LOCK (fd_table_lock);
-                fd_table[i].for_read = 0;
-                fd_table[i].for_write = 0;
-                fd_table[i].fd = -1;
-                fd_table[i].opaque = NULL;
-                UNLOCK (fd_table_lock);
+         q = fd_table[i].opaque;
+         assert (q);
+         assert (q->proc);
+         assert (!q->done);
+         any = 1;
+         if (q->handler (q->handler_value,
+                         q->proc->pid, fd_table[i].fd))
+           {
+             DEBUG2 ("setting fd %d (q=%p) done", fd_table[i].fd, q);
+             q->done = 1;
+             /* Free the table entry.  */
+             LOCK (fd_table_lock);
+             fd_table[i].for_read = 0;
+             fd_table[i].for_write = 0;
+             fd_table[i].fd = -1;
+             fd_table[i].opaque = NULL;
+             UNLOCK (fd_table_lock);
             }
         }
     }
     
-    return any;
+  return any;
 }
 
 
-
 /* 
  * called by rungpg.c to register something for select()
  */
 GpgmeError
-_gpgme_register_pipe_handler ( void *opaque, 
+_gpgme_register_pipe_handler (void *opaque, 
                               int (*handler)(void*,int,int),
                               void *handler_value,
-                              int pid, int fd, int inbound )
+                              int pid, int fd, int inbound)
 {
-    GpgmeCtx ctx = opaque;
-    struct wait_item_s *q;
-    struct proc_s *proc;
-    int i;
-
-    assert (opaque);
-    assert (handler);
-
-    /* Allocate a structure to hold info about the handler */
-    q = xtrycalloc ( 1, sizeof *q );
-    if ( !q )
-        return mk_error (Out_Of_Core);
-    q->inbound = inbound;
-    q->handler = handler;
-    q->handler_value = handler_value;
-
-    /* Put this into the process queue */
-    LOCK (proc_queue_lock);
-    for (proc=proc_queue; proc && proc->pid != pid; proc = proc->next)
-        ;
-    if (!proc) { /* a new process */
-        proc = xtrycalloc ( 1, sizeof *proc );
-        if (!proc) {
-            UNLOCK (proc_queue_lock);
-            return mk_error (Out_Of_Core);
+  GpgmeCtx ctx = opaque;
+  struct wait_item_s *q;
+  struct proc_s *proc;
+  int i;
+
+  assert (opaque);
+  assert (handler);
+
+  /* Allocate a structure to hold info about the handler.  */
+  q = xtrycalloc (1, sizeof *q);
+  if (!q)
+    return mk_error (Out_Of_Core);
+  q->inbound = inbound;
+  q->handler = handler;
+  q->handler_value = handler_value;
+
+  /* Put this into the process queue.  */
+  LOCK (proc_queue_lock);
+  for (proc = proc_queue; proc && proc->pid != pid; proc = proc->next)
+    ;
+  if (!proc)
+    {
+      /* A new process.  */
+      proc = xtrycalloc (1, sizeof *proc);
+      if (!proc)
+       {
+         UNLOCK (proc_queue_lock);
+         return mk_error (Out_Of_Core);
         }
-        proc->pid = pid;
-        proc->ctx = ctx;
-        proc->next = proc_queue;
-        proc_queue = proc;
+      proc->pid = pid;
+      proc->ctx = ctx;
+      proc->next = proc_queue;
+      proc_queue = proc;
     }
-    assert (proc->ctx == ctx);
-    q->proc = proc;
-    q->next = proc->handler_list;
-    proc->handler_list = q;
-    UNLOCK (proc_queue_lock);
+  assert (proc->ctx == ctx);
+  q->proc = proc;
+  q->next = proc->handler_list;
+  proc->handler_list = q;
+  UNLOCK (proc_queue_lock);
     
-    LOCK (fd_table_lock);
+  LOCK (fd_table_lock);
  again:  
-    for (i=0; i < fd_table_size; i++ ) {
-        if ( fd_table[i].fd == -1 ) {
-            fd_table[i].fd = fd;
-            fd_table[i].for_read = inbound;    
-            fd_table[i].for_write = !inbound;    
-            fd_table[i].signaled = 0;
-            fd_table[i].frozen = 0;
-            fd_table[i].opaque = q;
-            UNLOCK (fd_table_lock);
-            return 0;
+  for (i=0; i < fd_table_size; i++)
+    {
+      if (fd_table[i].fd == -1)
+       {
+         fd_table[i].fd = fd;
+         fd_table[i].for_read = inbound;    
+         fd_table[i].for_write = !inbound;    
+         fd_table[i].signaled = 0;
+         fd_table[i].frozen = 0;
+         fd_table[i].opaque = q;
+         UNLOCK (fd_table_lock);
+         return 0;
         }
     }
-    if ( fd_table_size < 50 ) {
-        /* FIXME: We have to wait until there are no other readers of the 
-         * table, i.e that the io_select is not active in another thread */
-        struct io_select_fd_s *tmp;
-
-        tmp = xtryrealloc ( fd_table, (fd_table_size + 10) * sizeof *tmp );
-        if ( tmp ) {
-            for (i=0; i < 10; i++ )
-                tmp[fd_table_size+i].fd = -1;
-            fd_table_size += i;
-            fd_table = tmp;
-            goto again;
-        }
-    }
-
-    UNLOCK (fd_table_lock);
-    xfree (q);
-    /* FIXME: remove the proc table entry */
-    return mk_error (Too_Many_Procs);
+  if ( fd_table_size < 50 ) {
+    /* FIXME: We have to wait until there are no other readers of the 
+     * table, i.e that the io_select is not active in another thread */
+    struct io_select_fd_s *tmp;
+    
+    tmp = xtryrealloc (fd_table, (fd_table_size + 10) * sizeof *tmp);
+    if (tmp)
+      {
+       for (i = 0; i < 10; i++)
+         tmp[fd_table_size+i].fd = -1;
+       fd_table_size += i;
+       fd_table = tmp;
+       goto again;
+      }
+  }
+
+  UNLOCK (fd_table_lock);
+  xfree (q);
+  /* FIXME: Remove the proc table entry.  */
+  return mk_error (Too_Many_Procs);
 }
 
 
 void
-_gpgme_freeze_fd ( int fd )
+_gpgme_freeze_fd (int fd)
 {
-    int i;
-
-    LOCK (fd_table_lock);
-    for (i=0; i < fd_table_size; i++ ) {
-        if ( fd_table[i].fd == fd ) {
-            struct wait_item_s *q;
-
-            fd_table[i].frozen = 1;
-            if ( (q=fd_table[i].opaque) )
-                q->frozen = 1;
-            DEBUG2 ("fd %d frozen (q=%p)", fd, q );
-            break;
+  int i;
+
+  LOCK (fd_table_lock);
+  for (i = 0; i < fd_table_size; i++)
+    {
+      if (fd_table[i].fd == fd)
+       {
+         struct wait_item_s *q;
+
+         fd_table[i].frozen = 1;
+         q = fd_table[i].opaque;
+         if (q)
+           q->frozen = 1;
+         DEBUG2 ("fd %d frozen (q=%p)", fd, q);
+         break;
         }
     }
-    UNLOCK (fd_table_lock);
+  UNLOCK (fd_table_lock);
 }
 
 void
-_gpgme_thaw_fd ( int fd )
+_gpgme_thaw_fd (int fd)
 {
-    int i;
-
-    LOCK (fd_table_lock);
-    for (i=0; i < fd_table_size; i++ ) {
-        if ( fd_table[i].fd == fd ) {
-            struct wait_item_s *q;
-
-            fd_table[i].frozen = 0;
-            if ( (q=fd_table[i].opaque) )
-                q->frozen = 0;
-            DEBUG2 ("fd %d thawed (q=%p)", fd, q );
-            break;
+  int i;
+
+  LOCK (fd_table_lock);
+  for (i = 0; i < fd_table_size; i++)
+    {
+      if (fd_table[i].fd == fd)
+       {
+         struct wait_item_s *q;
+
+         fd_table[i].frozen = 0;
+         q = fd_table[i].opaque;
+         if (q)
+           q->frozen = 0;
+         DEBUG2 ("fd %d thawed (q=%p)", fd, q);
+         break;
         }
     }
-    UNLOCK (fd_table_lock);
+  UNLOCK (fd_table_lock);
 }
 
 
@@ -374,9 +403,9 @@ _gpgme_thaw_fd ( int fd )
  * that is is idle.  NULL may be used to remove this function.
  **/
 void
-gpgme_register_idle ( void (*fnc)(void) )
+gpgme_register_idle (void (*fnc)(void))
 {
-    idle_function = fnc;
+  idle_function = fnc;
 }