scd: Fix resetting and closing of the reader. (Backported by gniibe)
authorWerner Koch <wk@gnupg.org>
Wed, 14 Dec 2011 09:30:01 +0000 (10:30 +0100)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 25 Jun 2012 01:04:22 +0000 (10:04 +0900)
* scd/command.c (update_card_removed): Do no act on an invalid VRDR.
(do_reset): Ignore apdu_reset error codes for no and inactive card.
Close the reader before setting the slot to -1.
(update_reader_status_file): Notify the application before closing the
reader.
--

With this change the scd now works as it did in the past.  In
particular there is no more endless loop trying to open the reader by
the update_reader_status_file ticker function.  That bug basically
blocked all card operations until the scdaemon was killed.

scd/command.c

index ccb25f1..7865869 100644 (file)
@@ -181,6 +181,9 @@ update_card_removed (int slot, int value)
 {
   struct server_local_s *sl;
 
+  if (slot == -1)
+    return;
+
   for (sl=session_list; sl; sl = sl->next_session)
     if (sl->ctrl_backlink
         && sl->ctrl_backlink->reader_slot == slot)
@@ -308,11 +311,19 @@ do_reset (ctrl_t ctrl, int send_reset)
      tell the application layer about it.  */
   if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
     {
-      if (apdu_reset (slot)) 
-        {
-          slot_table[slot].valid = 0;
-        }
       application_notify_card_reset (slot);
+      switch (apdu_reset (slot))
+       {
+       case 0:
+         break;
+       case SW_HOST_NO_CARD:
+       case SW_HOST_CARD_INACTIVE:
+         break;
+       default:
+         apdu_close_reader (slot);
+         slot_table[slot].slot = slot = -1;
+         break;
+       }
     }
 
   /* If we hold a lock, unlock now. */
@@ -1671,10 +1682,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
 
          ss = &slot_table[slot];
 
-         if (!ss->valid)
-           BUG ();
-
-         if (ss->any && (ss->status & 1))
+         if (ss->valid && ss->any && (ss->status & 1))
            flag = 'u';
        }
       rc = assuan_send_data (ctx, &flag, 1);
@@ -2213,6 +2221,7 @@ update_reader_status_file (int set_card_removed_flag)
       if (sw_apdu == SW_HOST_NO_READER)
         {
           /* Most likely the _reader_ has been unplugged.  */
+         application_notify_card_reset (ss->slot);
          apdu_close_reader (ss->slot);
          ss->valid = 0;
           status = 0;