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
-~----------~----~----~----~------~----~------~--~---

Reply via email to