Date: Thu, 18 Jul 2019 15:30:01 +0000 (UTC) From: Alan Somers <asomers@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r350113 - projects/fuse2/sys/fs/fuse Message-ID: <201907181530.x6IFU10M006793@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: asomers Date: Thu Jul 18 15:30:00 2019 New Revision: 350113 URL: https://svnweb.freebsd.org/changeset/base/350113 Log: fusefs: fix another semi-infinite loop bug regarding signal handling fticket_wait_answer would spin if it received an unhandled signal whose default disposition is to terminate. The reason is because msleep(9) would return EINTR even for a masked signal. One reason is when the thread is stopped, which happens for example during sigexit(). Fix this bug by returning immediately if fticket_wait_answer ever gets interrupted a second time, for any reason. Sponsored by: The FreeBSD Foundation Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.c Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.c ============================================================================== --- projects/fuse2/sys/fs/fuse/fuse_ipc.c Thu Jul 18 13:58:04 2019 (r350112) +++ projects/fuse2/sys/fs/fuse/fuse_ipc.c Thu Jul 18 15:30:00 2019 (r350113) @@ -439,11 +439,12 @@ fticket_wait_answer(struct fuse_ticket *ftick) sigset_t blockedset, oldset; int err = 0, stops_deferred; struct fuse_data *data; + bool interrupted = false; if (fsess_isimpl(ftick->tk_data->mp, FUSE_INTERRUPT)) { SIGEMPTYSET(blockedset); } else { - /* May as well block all signals */ + /* Block all signals except (implicitly) SIGKILL */ SIGFILLSET(blockedset); } stops_deferred = sigdeferstop(SIGDEFERSTOP_SILENT); @@ -489,7 +490,6 @@ retry: * or EAGAIN to the interrupt. */ sigset_t tmpset; - int sig; SDT_PROBE2(fusefs, , ipc, trace, 4, "fticket_wait_answer: interrupt"); @@ -498,22 +498,28 @@ retry: PROC_LOCK(td->td_proc); mtx_lock(&td->td_proc->p_sigacts->ps_mtx); - sig = cursig(td); tmpset = td->td_proc->p_siglist; SIGSETOR(tmpset, td->td_siglist); mtx_unlock(&td->td_proc->p_sigacts->ps_mtx); PROC_UNLOCK(td->td_proc); fuse_lck_mtx_lock(ftick->tk_aw_mtx); - if (!SIGISMEMBER(tmpset, SIGKILL)) { + if (!interrupted && !SIGISMEMBER(tmpset, SIGKILL)) { /* - * Block the just-delivered signal while we wait for an - * interrupt response + * Block all signals while we wait for an interrupt + * response. The protocol doesn't discriminate between + * different signals. */ - SIGADDSET(blockedset, sig); + SIGFILLSET(blockedset); + interrupted = true; goto retry; } else { - /* Return immediately for fatal signals */ + /* + * Return immediately for fatal signals, or if this is + * the second interruption. We should only be + * interrupted twice if the thread is stopped, for + * example during sigexit. + */ } } else if (err) { SDT_PROBE2(fusefs, , ipc, trace, 6,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907181530.x6IFU10M006793>