freebsd-ports/devel/libpdel/files/patch-util_paction.c
Sergey Matveychuk 14f229309b - Add two patches.
1) Fix a race condition. It prevents UDP sockets/descriptors leak when
     active RADIUS authorization used.
  2) FSM events processing optimization. System calls nubers reduced
     almost twice. (It makes mpd4 faster)

Submitted by:	Alexander Motin <mav_at_alkar.net>
Approved by:	software developers
2007-02-06 16:25:27 +00:00

54 lines
1.6 KiB
C

--- util/paction.c (revision 68)
+++ util/paction.c (working copy)
@@ -39,7 +39,7 @@
#endif
paction_finish_t *finish; /* action finisher */
void *arg; /* action argument */
- u_char started; /* action thread started */
+ u_char may_cancel; /* ok to cancel action thread */
u_char canceled; /* action was canceled */
};
@@ -118,10 +118,11 @@
/*
* Don't cancel the thread before paction_main() starts, because
- * then paction_cleanup() would never get invoked. Instead, use
- * the 'started' and 'canceled' flags to avoid this race condition.
+ * then paction_cleanup() would never get invoked. Also don't
+ * pthread_cancel() the thread after the handler has completed,
+ * because we might cancel in the middle of the cleanup.
*/
- if (action->started)
+ if (action->may_cancel)
pthread_cancel(action->tid);
/* Unlock action */
@@ -139,9 +140,9 @@
/* Cleanup when thread exits */
pthread_cleanup_push(paction_cleanup, action);
- /* Mark thread as started */
- assert(!action->started);
- action->started = 1; /* race condition ok */
+ /* Begin allowing pthread_cancel()'s */
+ assert(!action->may_cancel);
+ action->may_cancel = 1;
/* Handle race between paction_cancel() and paction_main() */
if (action->canceled) /* race condition ok */
@@ -151,6 +152,14 @@
(*action->handler)(action->arg);
done:;
+ /* Stop allowing pthread_cancel()'s */
+ MUTEX_LOCK(&action->mutex, action->mutex_count);
+ action->may_cancel = 0;
+ MUTEX_UNLOCK(&action->mutex, action->mutex_count);
+
+ /* Consume any last-minute pthread_cancel() still pending */
+ pthread_testcancel();
+
/* Done */
pthread_cleanup_pop(1);
return (NULL);