Подтвердить что ты не робот

Программное обеспечение Sandboxed Mac с исчерпывающими ресурсами URL

Я разрабатываю приложение Mac, которое запрашивает у пользователя файлы с использованием NSOpenPanel. Приложение изолировано (тестирование на OSX 10.9.4). Я заметил, что если я открываю большое количество файлов (~ 3000), открытая панель начинает испускать ошибки в журнале. Это также происходит, если я попытаюсь несколько раз открыть меньше файлов в патронах.

После того, как ошибки начнут появляться в первый раз, каждый раз, когда NSOpenPanel снова используется для открытия файлов, независимо от количества файлов, эти ошибки будут генерироваться снова (пока приложение не будет закрыто).

Сообщение об ошибке выглядит следующим образом:

TestPanel[98508:303] __41+[NSSavePanel _consumeSandboxExtensions:]_block_invoke: sandbox_consume_fs_extension failed

Одна строка для каждого файла, который я пытаюсь открыть.

Мне удалось воспроизвести это поведение с помощью простого приложения: изолированное приложение с одной кнопкой, вызывающее следующий код:

NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:YES];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
    NSLog(@"%lu", [panel.URLs count]);
}];

Ошибки появляются до того, как код достигнет обработчика завершения.

Кажется, что я все еще могу получить URL-адреса с панели в обработчике завершения, но он действительно загрязняет системный журнал.

EDIT:

Кажется, что эта проблема напрямую не связана с панелями NSOpenPanel/NSSavePanel. Очень похожее происходит при использовании drap/drop с файлами. Что-то вроде этого:

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
    ...
    NSPasteboard *pboard = [sender draggingPasteboard];
    if ([[pboard types] containsObject:NSURLPboardType]) {
        NSArray *urls = [pboard readObjectsForClasses:@[[NSURL class]] options:nil];
    }
    ...
}

Это приведет к появлению следующих сообщений журнала при перетаскивании большого количества файлов ( "магический" номер кажется где-то около 2900):

Consume sandbox extension for itemIdentifier (2937) from pasteboard failed!

Как и в случае с NSOpenPanel, после первого появления этого, каждый удаленный файл генерирует ту же ошибку в журнале.

ИЗМЕНИТЬ 2:

@mahal tertin ответ указал мне в правильном направлении. Проблема в том, что количество файлов и тот факт, что ресурсы ресурсов с ограниченным доступом ограничены.

Однако, похоже, не найдено разумного решения. Проблема заключается в том, что когда пользователь нажимает "ОК" на NSOpenPanel (или удаляет файлы с помощью элемента управления перетаскиванием), за кулисами ОС уже пытается создать эти URL-адреса с защитой и неявно вызывает startAccessingSecurityScopedResource для вас. Поэтому, если пользователь пытается открыть больше файлов, чем предел, ресурсы исчерпаны, и единственным вариантом является закрытие и перезапуск приложения.

Вызов stopAccessingSecurityScopedResource по возвращенным URL-адресам, похоже, освобождает ресурсы, однако это решение было обескуражено представителем Apple на официальном форуме разработчиков (ссылка находится за логином).

Похоже, что приложение находится на милости пользователя, чтобы не открывать слишком много файлов. И это даже не сразу, поскольку нет утвержденного способа выпуска этих ресурсов. Вы можете предупредить пользователя в документации или даже с предупреждением в приложении, но нет способа предотвратить их испортить приложение и принудительно перезапустить.

Итак, если приложение работает достаточно долго, и пользователь продолжает открывать файлы, приложение со временем станет непригодным.

Ищем разумное решение для этого.

4b9b3361

Ответ 1

После поиска высокого и низкого уровня и запроса в разных местах, я собираюсь закрыть этот вопрос и сделать вывод, что нет ответа или решения. Я размещаю известную информацию об этом для дальнейшего использования.

Все предлагаемые решения - это всего лишь обходные пути, которые могут свести к минимуму проблему и попытаться помочь пользователю не пытаться открыть слишком много файлов. Но нет ничего, что можно было бы сделать, чтобы реально решить эту проблему.

Вот известные факты об этой проблеме:

  • Независимо от того, что вы делаете, пользователь может попытаться открыть слишком много файлов в диалоговом окне NSOpenPanel и исчерпать ресурсы URL с ограничениями безопасности
  • Как только эти ресурсы исчерпаны, невозможно открыть больше файлов для чтения/записи. Приложение необходимо закрыть и вновь открыть.
  • Даже если пользователь не пытается открыть слишком много файлов одновременно, приложение все равно может исчерпать эти ресурсы, если оно работает достаточно долго, и пользователь со временем открывает достаточно файлов, поскольку startAccessingSecurityScopedResource вызывается автоматически для файлов, открытых с помощью NSOpenPanel (или механизм перетаскивания/перетаскивания), и ничто никогда не закрывает эти ресурсы.
  • Вызов stopAccessingSecurityScopedResource по всему URL-адресу, полученному открытой панелью, освободит эти ресурсы, но эта практика не поощряется Apple, заявив, что она может быть несовместима с будущими решениями.
  • Когда вы получаете список URL-адресов из NSOpenPanel (или перетаскивание/перетаскивание), невозможно определить, были ли удалены все URL-адреса или имеются ли URL-адреса, превышающие лимит и, следовательно, недействительные.
  • Apple знает об этом и может исправить это в будущем. Он по-прежнему не исправлен в 10.10 и, конечно, это не поможет текущим приложениям, запущенным в текущей/предыдущей версии OSX.

Кажется, Apple действительно сбросила мяч на этом, реализация Sandbox кажется очень неряшливой и недальновидной.

Ответ 2

Поведение, которое вы испытываете, связано с ограниченностью ресурсов с ограниченным доступом:

NSURL - (BOOL) startAccessingSecurityScopedResource сообщает

Если ресурсы ядра исчерпаны, ваше приложение теряет способность для добавления местоположений файловой системы в свою песочницу...

Текущий предел примерно соответствует тому, что вы испытали. Видеть: Каковы текущие ограничения ресурса ядра для закладок безопасности?

Чтобы предотвратить это:

  • только начинает доступ к тем SSB, которые вам нужны в данный момент времени, а затем прекратите доступ к ним.
  • запустите доступ к файлам, а не к папкам: попросите пользователя не выбирать файлы, а полную папку. Это предоставит вам доступ ко всему дереву под этим каталогом
  • on draggingEntered: показать NSOpenPanel с закрывающейся директорией (-ями) для предоставления доступа