Skip to content

Call fuse_daemonize before fuse_mount #373

Description

@dmik

The current order affects macFUSE 5.2.0+ which switched to ObjC MFMount.framework in libfuse. Using fork after touching some ObjC objects and then touching them again in the child after fork is not supported on macOS and triggers its own fork guard that terminates the sshfs process:

Thread 3 Crashed:
0   libsystem_kernel.dylib        	       0x180efeb10 __abort_with_payload + 8
1   libsystem_kernel.dylib        	       0x180f260e8 abort_with_payload_wrapper_internal + 104
2   libsystem_kernel.dylib        	       0x180f26080 abort_with_reason + 32
3   libobjc.A.dylib               	       0x180b105ec _objc_fatalv(unsigned long long, unsigned long long, char const*, char*) + 128
4   libobjc.A.dylib               	       0x180b1056c _objc_fatal(char const*, ...) + 44
5   libobjc.A.dylib               	       0x180af4b10 performForkChildInitialize(objc_class*, objc_class*) + 396
6   libobjc.A.dylib               	       0x180ada7d0 initializeNonMetaClass + 620
7   libobjc.A.dylib               	       0x180af6258 initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool) + 176
8   libobjc.A.dylib               	       0x180ad9f8c lookUpImpOrForward + 288
9   libobjc.A.dylib               	       0x180ad9b84 _objc_msgSend_uncached + 68
10  MFMount                       	       0x1035d2f0c specialized static Bridge.log(level:function:_:) + 564
11  MFMount                       	       0x1035dfa9c closure #1 in MFChannelCopyNextMessage(_:) + 232
12  MFMount                       	       0x1035df984 MFChannelCopyNextMessage + 32
13  libfuse3.4.dylib              	       0x102718880 0x102700000 + 100480
14  libfuse3.4.dylib              	       0x1027140b4 0x102700000 + 82100
15  libsystem_pthread.dylib       	       0x180f35c58 _pthread_start + 136
16  libsystem_pthread.dylib       	       0x180f30c1c thread_start + 8

…

Thread 3 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000008   x1: 0x0000000000000001   x2: 0x0000000000000000   x3: 0x0000000000000000
    x4: 0x00000001039423b0   x5: 0x0000000000000080   x6: 0xffffffffbfc007ff   x7: 0xfffff0003ffff800
    x8: 0x0000000000000020   x9: 0x0000000000001c03  x10: 0x0000000103942130  x11: 0x0000000103942080
   x12: 0x0000000000000004  x13: 0x0000000000001359  x14: 0x0000000004000000  x15: 0x000000000000002b
   x16: 0x0000000000000209  x17: 0x00000001ee77b190  x18: 0x0000000000000000  x19: 0x0000000000000080
   x20: 0x00000001039423b0  x21: 0x0000000000000000  x22: 0x0000000000000000  x23: 0x0000000000000001
   x24: 0x0000000000000008  x25: 0x000000016de370e0  x26: 0x00000001ea670000  x27: 0x00000001ed13648c
   x28: 0x000000016de370e0   fp: 0x000000016de36b10   lr: 0x0000000180f260e8
    sp: 0x000000016de36ad0   pc: 0x0000000180efeb10 cpsr: 0x40001000
   far: 0x0000000000000000  esr: 0x56000080 (Syscall)

Binary Images:
       0x1021f4000 -        0x102203fff sshfs (*) <44561020-c195-3898-b4ff-5acf36d45ef8> /Volumes/VOLUME/*/sshfs
       0x102700000 -        0x10272ffff libfuse3.4.dylib (*) <cd74eae7-b278-377d-86fd-664f04628378> /usr/local/lib/libfuse3.4.dylib
       0x102364000 -        0x10245ffff libglib-2.0.0.dylib (*) <31e21c05-0fe3-3331-a56f-9e819e39cc0c> /opt/homebrew/*/libglib-2.0.0.dylib
       0x1035d0000 -        0x103713fff io.macfuse.frameworks.mount (2.1) <49484faa-8015-3f8a-83a5-aa4134c4c744> /Library/Filesystems/macfuse.fs/Contents/Frameworks/MFMount.framework/Versions/A/MFMount
       0x10224c000 -        0x102273fff libintl.8.dylib (*) <9ef58f71-571d-352e-bb98-6e9754d6b30b> /opt/homebrew/*/libintl.8.dylib
       0x1024b4000 -        0x10252bfff libpcre2-8.0.dylib (*) <ac59ae27-0884-3df1-baf1-38015aa7768b> /opt/homebrew/*/libpcre2-8.0.dylib
       0x180ef1000 -        0x180f2e2af libsystem_kernel.dylib (*) <fca53b98-3d6a-38b2-a0ec-df0f7e05f171> /usr/lib/system/libsystem_kernel.dylib
       0x180d79000 -        0x180dc023f libdispatch.dylib (*) <f071efe4-299f-3089-acc4-0025b8ffb52a> /usr/lib/system/libdispatch.dylib
       0x180b58000 -        0x180bfe217 dyld (*) <f924bdd3-4365-3466-9580-8b1b3fa8f857> /usr/lib/dyld
               0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???
       0x180f3c000 -        0x180f44963 libsystem_platform.dylib (*) <160fd864-8d15-36fc-9e97-9725388cfafe> /usr/lib/system/libsystem_platform.dylib
       0x180ad0000 -        0x180b22b4b libobjc.A.dylib (*) <ff1d8ae4-abef-35f1-a30a-1183b9cb414f> /usr/lib/libobjc.A.dylib
       0x180f2f000 -        0x180f3bb3b libsystem_pthread.dylib (*) <4f33683c-18c8-39a1-800b-2e3bd43bcc13> /usr/lib/system/libsystem_pthread.dylib

macFUSE 5.3.3 went further and now always forces sshfs to run in foreground (as if -f was given) to protect from this crash which is inconvenient (at least).

See also #371 (comment) for some more details.

The fix seems to be trivial - just move fuse_daemonize before fuse_mount. I tested it locally and daemonization works well again, as well as the mounted filesystem, no visible issues after a VS Code stress test on a large project. While reordering can be only made macOS-specific, I don't think it's necessary. Calling fuse_daemonize right after fuse_new and before anything else (e.g. before fuse_mount) seems to be the right way on any platform.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions