Good afternoon, When I was working on NTFS-3G, I tried to avoid modifying FUSE or ntfs-3g itself. Instead, I just wrote a short daemon that blocked on sigsuspend() until it received SIGTERM, SIGQUIT, or SIGINT.
If it received SIGTERM from its parent (i.e. launchd), that implies system shutdown. Then I would scan mounted filesystems with getmntinfo() looking for those of type "fusefs," and unmount() those, perhaps with MNT_FORCE. With some of the changes to MacFUSE, you may also want to scan for anything of a type matching "fusefs_*" as well. This would cause the ntfs-3g binary to terminate cleanly, without needing to handle SIGTERM. A more advisable option would be to go through DiskArbitration and give DADiskUnmount() a shot before resorting to unmount(), which will assure proper notifications get sent to things like Spotlight before the volume is forcibly unmounted. It worked for me, at the time. Hope this helps, - Paul On Feb 6, 2008, at 4:04 AM, Erik Larsson wrote: > > Hi group, hi Amit. > > I'm maintaining an ntfs-3g package for OS X at > http://macntfs-3g.blogspot.com and I'm struggling with an issue where > the ntfs-3g process locks up at shutdown, and has to be SIGKILL'd by > the > OS after a delay of 30 seconds. > ntfs-3g is not doing any signal handling itself in the current > version, > and instead passes that responsibility over the fuse library by > invoking: > > fuse_set_signal_handlers(fuse_get_session(struct fuse*)) > > When I send the ntfs-3g process SIGTERM under "normal" > circumstances, in > a non-shutdown situation, there is no problem. ntfs-3g terminates > gracefully. Some kind of deadlock seems to occur when this is done > in a > shutdown situation though. > > I looked through the MacFUSE patchset and found a modification to > fuse_signals.c which seems suspicious to me (scroll down to the end of > the mail to see what I'm talking about). I don't have a very good view > of the internal structure of fuse, but it seems like a fair assumption > that fuse_signals.c takes care of signal handling. > In the below code snippet, the exit_handler forks (seems dangerous > to me > in a shutdown situation where processes are killed off all the time), > and invokes the command /sbin/umount . I'm suggesting that this > behavior > is somehow causing the lockup, but I have no real "evidence" for it, > just thoughts. > > As a workaround, I have written a daemon, fuse_daemon (actually a > reimplementation of Paul Marks' utility for the older ntfs-3g package) > that waits in the background until it gets SIGTERM, and then iterates > through all fuse file systems and unmounts them cleanly. This only > seems > to work if fuse_daemon gets SIGTERM before ntfs-3g does, so signal > handling in ntfs-3g needs to be turned off completely for this > solution > work. > > I hope you realize the serious implication of this problem... if > ntfs-3g > (or indeed any other FUSE file system) doesn't terminate gracefully, > it > might leave the user's hard drive in an inconsistent state, worst > case. > Has anyone encountered this issue before, and solved it without having > an external daemon manage unmounting of file systems? > > - Erik Larsson > > --------- > diff -Naur old/lib/fuse_signals.c new/lib/fuse_signals.c > --- old/lib/fuse_signals.c 2007-10-16 09:35:23.000000000 -0700 > +++ new/lib/fuse_signals.c 2008-01-01 15:56:28.000000000 -0800 > @@ -13,12 +13,45 @@ > #include <signal.h> > > static struct fuse_session *fuse_instance; > +#if (__FreeBSD__ >= 10) > +extern char *fuse_session_get_mntonname(struct fuse_session *se); > + > +#include <unistd.h> > + > +int > +fuse_chan_fd_np(void) > +{ > + if (fuse_instance && !fuse_session_exited(fuse_instance)) { > + return fuse_chan_fd(fuse_session_next_chan(fuse_instance, > NULL)); > + } else { > + return -1; > + } > +} > + > +#endif > > static void exit_handler(int sig) > { > (void) sig; > +#if (__FreeBSD__ >= 10) > + if (fuse_instance && !fuse_session_exited(fuse_instance)) { > + int fd; > + pid_t pid; > + > + fd = fuse_chan_fd(fuse_session_next_chan(fuse_instance, > NULL)); > + pid = fork(); > + if (pid == 0) { /* child */ > + char *mntonname = > fuse_session_get_mntonname(fuse_instance); > + fcntl(fd, F_SETFD, 1); /* close-on-exec */ > + execl("/sbin/umount", "/sbin/umount", mntonname, NULL); > + } else { > + /* We do nothing in the parent. */ > + } > + } > +#else > if (fuse_instance) > fuse_session_exit(fuse_instance); > +#endif > } > > static int set_one_signal_handler(int sig, void (*handler)(int)) > --------- > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "macfuse-devel" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/macfuse-devel?hl=en -~----------~----~----~----~------~----~------~--~---
