owntone/owntone-server

Not working on MacOs Sonoma 14.7

LordMyschkin opened this issue · 8 comments

After installing and doing a testrun, i noticed that owntone runs into a "too much open files" problem; After scanning ~23600 files, it reports

[2024-09-09 22:39:36] [  LOG]     scan: Scanned 23600 files...
[2024-09-09 22:39:36] [  LOG]     scan: Could not open directory /Volumes/SD512/collections/marla_glen/our_world: Too many open files

and every command I run either running mpc add, cantata or the webinterface errors about
e.g. the webinterface

[2024-09-09 22:54:02] [ LOG] httpd: Could not open /Users/martinroth/owntone_data/usr/share/owntone/htdocs/index.html: Too many open files

mpc stats reports that ot added 23325 Songs (out of about 45k).

May there be a file handler that should get freed or something?

On MacOS/BSD, OwnTone relies on libinotify-kqueue for monitoring the library. As the description says "Since the heart of the library is kqueue(2), the library has to keep many files open to provide proper monitoring". That is probably why you are getting this error. I think the library is keeping one file open per directory (or maybe even one per file?).

They also write "You can run out of file descriptors, so do not forget request more with setrlimit(2) before starting monitoring.", but I'm not sure how exactly that works.

It's been some years since I looked at the last time, but back then Mac/BSD didn't offer a better method of monitoring large libraries - i.e. one that wouldn't require keeping files open.

Did you try increasing the limit? Google says it can be done with "ulimit -n 10240"

I've looked some more into this, and according to the internet Mac OS has pretty good alternative to libinotify-kqueue, which is called File System Events. Perhaps it would be possible to add support for that, but a problem is that I can't test it.

I asked Claude.ai what the code for this API would look like, and it gave the below. Can you build (gcc -o fsevents_monitor fsevents_monitor.c -framework CoreServices) and run to see if it works?

#include <CoreServices/CoreServices.h>
#include <stdio.h>

void callback(
    ConstFSEventStreamRef streamRef,
    void *clientCallBackInfo,
    size_t numEvents,
    void *eventPaths,
    const FSEventStreamEventFlags eventFlags[],
    const FSEventStreamEventId eventIds[])
{
    int i;
    char **paths = eventPaths;

    for (i = 0; i < numEvents; i++) {
        printf("Change %llu in %s\n", eventIds[i], paths[i]);
    }
}

int main(int argc, const char * argv[]) {
    CFStringRef mypath = CFStringCreateWithCString(NULL, "/path/to/monitor", kCFStringEncodingUTF8);
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
    
    FSEventStreamContext context = {0, NULL, NULL, NULL, NULL};
    FSEventStreamRef stream = FSEventStreamCreate(
        NULL,
        &callback,
        &context,
        pathsToWatch,
        kFSEventStreamEventIdSinceNow,
        1.0,
        kFSEventStreamCreateFlagFileEvents
    );

    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);

    printf("Monitoring directory: /path/to/monitor\n");
    printf("Press Ctrl+C to stop\n");

    CFRunLoopRun();

    FSEventStreamStop(stream);
    FSEventStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    FSEventStreamInvalidate(stream);
    FSEventStreamRelease(stream);
    CFRelease(pathsToWatch);
    CFRelease(mypath);

    return 0;
}

It builds with warnings and runs without problem.

gcc -o fsevents_monitor fsevents_monitor.c -framework CoreServices
fsevents_monitor.c:35:5: warning: 'FSEventStreamScheduleWithRunLoop' is deprecated: first deprecated in macOS 13.0 - Use FSEventStreamSetDispatchQueue instead. [-Wdeprecated-declarations]
    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/FSEvents.framework/Headers/FSEvents.h:1153:1: note: 'FSEventStreamScheduleWithRunLoop' has been explicitly marked deprecated here
FSEventStreamScheduleWithRunLoop(
^
fsevents_monitor.c:44:5: warning: 'FSEventStreamUnscheduleFromRunLoop' is deprecated: first deprecated in macOS 13.0 - Use FSEventStreamSetDispatchQueue instead. [-Wdeprecated-declarations]
    FSEventStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/FSEvents.framework/Headers/FSEvents.h:1183:1: note: 'FSEventStreamUnscheduleFromRunLoop' has been explicitly marked deprecated here
FSEventStreamUnscheduleFromRunLoop(
^
2 warnings generated.
./fsevents_monitor
Monitoring directory: /path/to/monitor
Press Ctrl+C to stop
^C

Does it catch filesystem events? I.e. set /path/to/monitor to something and try to:

  1. Create a file
  2. Open a file (in an editor)
  3. Save the file
  4. Change file attributes
  5. Rename the file

Yes, that seems to work. I catches creation of the file, attribute change and renaming:

Monitoring directory: /Users/martinroth/src
Press Ctrl+C to stop
Change 69506105 in /Users/martinroth/src/Neuer Ordner
Change 69506117 in /Users/martinroth/src/.DS_Store
Change 69506302 in /Users/martinroth/src/.DS_Store
Change 69507026 in /Users/martinroth/src/Neuer Ordner
Change 69507027 in /Users/martinroth/src/Test
Change 69516956 in /Users/martinroth/src/testfile
Change 69520902 in /Users/martinroth/src/testfile
Change 69531325 in /Users/martinroth/src/testfile
Change 69534302 in /Users/martinroth/src/testfile
Change 69534303 in /Users/martinroth/src/testfile2
```

Which change is what?

I created a new folder, Renamed it to Test, then touched a testfile, change it to read only, changed it back and renamed it to testfile2 (Sorry for the confusion with the new folder, was just the only thing i could create in finder...
So every change should be reported...