fusefs: multiple interruptility improvements
- Don't explicitly not mask SIGKILL. kern_sigprocmask won't allow it to be masked, anyway.
- Fix an infinite loop bug. If a process received both a maskable signal lower than 9 (like SIGINT) and then received SIGKILL, fticket_wait_answer would spin. msleep would immediately return EINTR, but cursig would return SIGINT, so the sleep would get retried. Fix it by explicitly checking whether SIGKILL has been received.
- Abandon the sig_isfatal optimization introduced by r346357. That optimization would cause fticket_wait_answer to return immediately, without waiting for a response from the server, if the process were going to exit anyway. However, it's vulnerable to a race:
- fatal signal is received while fticket_wait_answer is sleeping.
- fticket_wait_answer sends the FUSE_INTERRUPT operation.
- fticket_wait_answer determines that the signal was fatal and returns without waiting for a response.
- Another thread changes the signal to non-fatal.
- The first thread returns to userspace. Instead of exiting, the process continues.
- The application receives EINTR, wrongly believes that the operation was successfully interrupted, and restarts it. This could cause problems for non-idempotent operations like FUSE_RENAME.
Reported by: kib (the race part)
Sponsored by: The FreeBSD Foundation