From owner-svn-src-stable@freebsd.org Mon Oct 10 04:57:34 2016 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D0890C0B360; Mon, 10 Oct 2016 04:57:34 +0000 (UTC) (envelope-from julian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A01D62B; Mon, 10 Oct 2016 04:57:34 +0000 (UTC) (envelope-from julian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u9A4vXAM092951; Mon, 10 Oct 2016 04:57:33 GMT (envelope-from julian@FreeBSD.org) Received: (from julian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u9A4vXlI092950; Mon, 10 Oct 2016 04:57:33 GMT (envelope-from julian@FreeBSD.org) Message-Id: <201610100457.u9A4vXlI092950@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: julian set sender to julian@FreeBSD.org using -f From: Julian Elischer Date: Mon, 10 Oct 2016 04:57:33 +0000 (UTC) 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 X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Oct 2016 04:57:34 -0000 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"));