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(¤t->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(¤t->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