Skip to content

Commit c166e29

Browse files
Support indexing within the SwiftPM plugin sandbox (#66)
Resolves rdar://86786641. ## Summary Resolves an issue when running DocC within the SwiftPM plugin sandbox where LMDBs calls to `flock()`, which in turn call `fsctl()` are blocked by the SwiftPM plugin sandbox. ## Details Running `docc convert` with the `--index` flag from within a SwiftPM plugin results in the following error: ``` [31m[1merror: [0m'docc convert' invocation failed with a nonzero exit code: '5'. [plugin 'Swift-DocC Convert'] Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PackagePlugin.PackageManagerProxyError.unspecified("ExitCode(rawValue: 1)") [plugin 'Swift-DocC Convert'] 2021-12-17 10:47:27.747972-0800 Swift_DocC_Convert[93764:6330351] Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PackagePlugin.PackageManagerProxyError.unspecified("ExitCode(rawValue: 1)") error: plugin process ended by an uncaught signal: 5 <command: /usr/bin/sandbox-exec -p '(version 1) (deny default) (import "system.sb") (allow file-read*) (allow process*) (allow file-write* (subpath "~/Developer/swift-docc-plugin/.build/plugins/outputs") (subpath "~/Developer/swift-docc-plugin/.build/plugins/cache") (subpath "/private/tmp") (subpath "/private/var/folders/8s/x4xvy8gd3m9c4r3zgdsqv9nh0000gn/T") ) ' ~/Developer/swift-docc-plugin/.build/plugins/cache/Swift_DocC_Convert>, <output: 'Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PackagePlugin.PackageManagerProxyError.unspecified("ExitCode(rawValue: 1)") 2021-12-17 10:47:27.747972-0800 Swift_DocC_Convert[93764:6330351] Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PackagePlugin.PackageManagerProxyError.unspecified("ExitCode(rawValue: 1)") '> ``` Using the `fs_usage` tool, we determined that the sandbox is blocking a call to `fsctl()` and throwing an error. `fsctl()` is used by the Darwin implementation of `flock()` which is used by LMDBs locking mechanism However, it turns out we don't have a need to run LMDB with locking here. Per the LMDB docs: > `MDB_NOLOCK:` > Don't do any locking. > If concurrent access is anticipated, the caller must > manage all concurrency itself. (https://github.com/LMDB/lmdb/blob/48a7fed59a8aae623deff415dda27097198ca0c1/libraries/liblmdb/lmdb.h#L619) DocC is creating a new database here and will be the only client to it while writing data- so concurrent access across processes is not anticipated. We already manage in-process access to the LMDB database to ensure it's not concurrent. Passing `.noLock` to the LMDB environment will not regress DocC's existing experience and allows DocC to run without issue in the SwiftPM sandbox. ## Testing Existing tests continue to pass. An integration test that confirms DocC is able to build a DocC archive that includes an index when run as part of a SwiftPM plugin will be included in the Swift-DocC-Plugin project and run as part of CI when the plugin is published.
1 parent b08ac7f commit c166e29

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

Sources/SwiftDocC/Indexing/Navigator/NavigatorIndex.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public class NavigatorIndex {
189189
*/
190190
fileprivate init(withEmptyTree url: URL, bundleIdentifier: String) throws {
191191
self.url = url
192-
self.environment = try LMDB.Environment(path: url.path, flags: [], maxDBs: 4, mapSize: 100 * 1024 * 1024) // mapSize = 100MB
192+
self.environment = try LMDB.Environment(path: url.path, flags: [.noLock], maxDBs: 4, mapSize: 100 * 1024 * 1024) // mapSize = 100MB
193193
self.database = try environment.openDatabase(named: "index", flags: [.create])
194194
self.information = try environment.openDatabase(named: "information", flags: [.create])
195195
self.availability = try environment.openDatabase(named: "availability", flags: [.create])

0 commit comments

Comments
 (0)