As per request from discussions in
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=241780
a patch against git.

Best regards

Anders Blomdell
--- autofs/lib/alarm.c  2007-06-07 15:05:03.000000000 +0200
+++ /usr/src/autofs/autofs.patched/lib/alarm.c  2007-06-07 15:08:29.000000000 
+0200
@@ -28,16 +28,16 @@
 
 #define alarm_lock() \
 do { \
-       int _alm_lock = pthread_mutex_lock(&mutex); \
-       if (_alm_lock) \
-               fatal(_alm_lock); \
+       int status = pthread_mutex_lock(&mutex); \
+       if (status) \
+               fatal(status); \
 } while (0)
 
 #define alarm_unlock() \
 do { \
-       int _alm_unlock = pthread_mutex_unlock(&mutex); \
-       if (_alm_unlock) \
-               fatal(_alm_unlock); \
+       int status = pthread_mutex_unlock(&mutex); \
+       if (status) \
+               fatal(status); \
 } while (0)
 
 void dump_alarms(void)
@@ -168,87 +168,65 @@
 static void *alarm_handler(void *arg)
 {
        struct list_head *head;
-       struct timespec expire;
-       time_t now;
        int status;
-
+       
        alarm_lock();
 
        head = &alarms;
 
        while (1) {
-               struct alarm *current;
-
-               /*
-                * If the alarm list is empty, wait until an alarm is
-                * added.
-                */
-               while (list_empty(head)) {
+               if (list_empty(head)) {
+                       /* No alarms, wait for one to be added */
                        status = pthread_cond_wait(&cond, &mutex);
                        if (status)
                                fatal(status);
-               }
-
-               current = list_entry(head->next, struct alarm, list);
-
-               now = time(NULL);
-
-               if (current->time <= now) {
-                       struct autofs_point *ap;
-
-                       list_del(&current->list);
-
-                       if (current->cancel) {
-                               free(current);
-                               continue;
-                       }
-
-                       ap = current->ap;
-                       free(current);
-                       alarm_unlock();
-
-                       state_mutex_lock(ap);
-                       nextstate(ap->state_pipe[1], ST_EXPIRE);
-                       state_mutex_unlock(ap);
-
-                       alarm_lock();
-                       continue;
-               }
-
-               expire.tv_sec = current->time;
-               expire.tv_nsec = 0;
-
-               while (1) {
-                       struct autofs_point *ap;
-                       struct alarm *next;
-
-                       status = pthread_cond_timedwait(&cond, &mutex, &expire);
-                       if (status && status != ETIMEDOUT)
-                               fatal(status);
-
-                       next = list_entry(head->next, struct alarm, list);
-                       if (next->cancel) {
-                               list_del(&next->list);
-                               free(next);
-                               break;
+               } else {
+                       struct alarm *first;
+                       time_t now;
+
+                       first = list_entry(head->next, struct alarm, list);
+
+                       now = time(NULL);
+
+                       if (first->time > now) {
+                               /* Wait for alarm to trigger or a new alarm 
+                                  to be added */
+                               struct timespec expire;
+
+                               expire.tv_sec = first->time;
+                               expire.tv_nsec = 0;
+
+                               status = pthread_cond_timedwait(&cond, &mutex,
+                                                               &expire);
+                               if (status && status != ETIMEDOUT)
+                                       fatal(status);
+                       } else {
+                               /* First alarm has triggered, run it */
+                               struct autofs_point *ap;
+
+                               list_del(&first->list);
+                               ap = first->ap;
+                               if (!first->cancel) {
+                                       /* We need to unlock the alarm list 
+                                          in case some other thread holds 
+                                          the state_mutex_lock(ap), and is 
+                                          currently trying to do some 
+                                          alarm_* function (i.e if we don't 
+                                          unlock, we might deadlock) */
+                                       alarm_unlock(); 
+
+                                       state_mutex_lock(ap);
+                                       nextstate(ap->state_pipe[1], 
+                                                 ST_EXPIRE);
+                                       state_mutex_unlock(ap);
+
+                                       alarm_lock();
+                               }
+                               free(first);
                        }
-
-                       if (next != current)
-                               break;
-
-                       list_del(&current->list);
-                       ap = current->ap;
-                       free(current);
-                       alarm_unlock();
-
-                       state_mutex_lock(ap);
-                       nextstate(ap->state_pipe[1], ST_EXPIRE);
-                       state_mutex_unlock(ap);
-
-                       alarm_lock();
-                       break;
                }
        }
+       /* Will never come here, so alarm_unlock is not necessary */
 }
 
 int alarm_start_handler(void)
_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs

Reply via email to