Date: Mon, 10 Oct 2016 04:57:33 +0000 (UTC) From: Julian Elischer <julian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r306935 - stable/10/sys/kern Message-ID: <201610100457.u9A4vXlI092950@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: julian Date: Mon Oct 10 04:57:33 2016 New Revision: 306935 URL: https://svnweb.freebsd.org/changeset/base/306935 Log: While the thread is sleeping in taskqueue_drain_all() it is posible that the queue entry it is looking at is removed from the queue, but we make no effort to account for this. when we wake up we need to check it's still there. PR: 209580 Sponsored by: Panzura inc Differential Revision: D8160 Modified: stable/10/sys/kern/subr_taskqueue.c Modified: stable/10/sys/kern/subr_taskqueue.c ============================================================================== --- stable/10/sys/kern/subr_taskqueue.c Mon Oct 10 04:53:15 2016 (r306934) +++ stable/10/sys/kern/subr_taskqueue.c Mon Oct 10 04:57:33 2016 (r306935) @@ -454,9 +454,26 @@ taskqueue_drain_all(struct taskqueue *qu TQ_LOCK(queue); task = STAILQ_LAST(&queue->tq_queue, task, ta_link); - if (task != NULL) - while (task->ta_pending != 0) - TQ_SLEEP(queue, task, &queue->tq_mutex, PWAIT, "-", 0); + while (task != NULL && task->ta_pending != 0) { + struct task *oldtask; + TQ_SLEEP(queue, task, &queue->tq_mutex, PWAIT, "-", 0); + /* + * While we were asleeep the last entry may have been freed. + * We need to check if it's still even in the queue. + * Not perfect, but it's better than referencing bad memory. + * first guess is the current 'end of queue' but if a new + * item has been added we need to take the expensive path + * Better fix in 11. + */ + oldtask = task; + if (oldtask != + (task = STAILQ_LAST(&queue->tq_queue, task, ta_link))) { + STAILQ_FOREACH(task, &queue->tq_queue, ta_link) { + if (task == oldtask) + break; + } + } + } taskqueue_drain_running(queue); KASSERT(STAILQ_EMPTY(&queue->tq_queue), ("taskqueue queue is not empty after draining"));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610100457.u9A4vXlI092950>