Skip to content

Commit 4c860b0

Browse files
authored
Fix various crashes and memory leaks (#520)
1 parent f23a2e5 commit 4c860b0

16 files changed

+79
-13237
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. Take a look
66

77
## [Unreleased]
88

9+
* The Readium Swift toolkit now requires a minimum of iOS 13.4.
10+
911
### Changed
1012

1113
#### Shared

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import PackageDescription
1010
let package = Package(
1111
name: "Readium",
1212
defaultLocalization: "en",
13-
platforms: [.iOS(.v13)],
13+
platforms: [.iOS("13.4")],
1414
products: [
1515
.library(name: "ReadiumShared", targets: ["ReadiumShared"]),
1616
.library(name: "ReadiumStreamer", targets: ["ReadiumStreamer"]),

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ This toolkit is a modular project, which follows the [Readium Architecture](http
1818

1919
| Readium | iOS | Swift compiler | Xcode |
2020
|-----------|------|----------------|-------|
21-
| `develop` | 13.0 | 5.10 | 15.4 |
22-
| 3.0.0 | 13.0 | 5.10 | 15.4 |
21+
| `develop` | 13.4 | 5.10 | 15.4 |
22+
| 3.0.0 | 13.4 | 5.10 | 15.4 |
2323
| 2.5.1 | 11.0 | 5.6.1 | 13.4 |
2424
| 2.5.0 | 10.0 | 5.6.1 | 13.4 |
2525
| 2.4.0 | 10.0 | 5.3.2 | 12.4 |

Sources/Shared/Publication/Locator.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,11 @@ public struct Locator: Hashable, CustomStringConvertible, Loggable, Sendable {
300300
let highlight = highlight,
301301
!highlight.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
302302
else {
303-
preconditionFailure("highlight is nil")
303+
return Locator.Text(
304+
after: after.takeIf { !$0.isEmpty },
305+
before: before.takeIf { !$0.isEmpty },
306+
highlight: nil
307+
)
304308
}
305309

306310
let range = range

Sources/Shared/Toolkit/File/FileResource.swift

+16-8
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,24 @@ public actor FileResource: Resource, Loggable {
5353
}
5454

5555
public func stream(range: Range<UInt64>?, consume: @escaping (Data) -> Void) async -> ReadResult<Void> {
56-
await handle().map { handle in
57-
if let range = range {
58-
handle.seek(toFileOffset: UInt64(max(0, range.lowerBound)))
59-
consume(handle.readData(ofLength: Int(range.upperBound - range.lowerBound)))
60-
} else {
61-
handle.seek(toFileOffset: 0)
62-
consume(handle.readDataToEndOfFile())
56+
await handle().flatMap { handle in
57+
do {
58+
if let range = range {
59+
try handle.seek(toOffset: UInt64(max(0, range.lowerBound)))
60+
if let data = try handle.read(upToCount: Int(range.upperBound - range.lowerBound)) {
61+
consume(data)
62+
}
63+
} else {
64+
try handle.seek(toOffset: 0)
65+
if let data = try handle.readToEnd() {
66+
consume(data)
67+
}
68+
}
69+
} catch {
70+
return .failure(.access(.fileSystem(.io(error))))
6371
}
6472

65-
return ()
73+
return .success(())
6674
}
6775
}
6876

Sources/Shared/Toolkit/HTTP/DefaultHTTPClient.swift

+14-6
Original file line numberDiff line numberDiff line change
@@ -253,27 +253,31 @@ public final class DefaultHTTPClient: HTTPClient, Loggable {
253253

254254
func start(
255255
request: HTTPRequest,
256-
task: URLSessionDataTask,
256+
task sessionTask: URLSessionDataTask,
257257
receiveResponse: @escaping HTTPTask.ReceiveResponse,
258258
receiveChallenge: @escaping HTTPTask.ReceiveChallenge,
259259
consume: @escaping HTTPTask.Consume
260260
) async -> HTTPResult<HTTPResponse> {
261261
let task = HTTPTask(
262262
request: request,
263-
task: task,
263+
task: sessionTask,
264264
receiveResponse: receiveResponse,
265265
receiveChallenge: receiveChallenge,
266266
consume: consume
267267
)
268268
$tasks.write { $0.append(task) }
269269

270-
return await withTaskCancellationHandler {
270+
let result = await withTaskCancellationHandler {
271271
await withCheckedContinuation { continuation in
272272
task.start(with: continuation)
273273
}
274274
} onCancel: {
275275
task.cancel()
276276
}
277+
278+
$tasks.write { $0.removeAll { $0.task == sessionTask } }
279+
280+
return result
277281
}
278282

279283
private func findTask(for urlTask: URLSessionTask) -> HTTPTask? {
@@ -373,6 +377,10 @@ public final class DefaultHTTPClient: HTTPClient, Loggable {
373377
self.consume = consume
374378
}
375379

380+
deinit {
381+
finish()
382+
}
383+
376384
func start(with continuation: Continuation) {
377385
log(.info, request)
378386
state = .start(continuation: continuation)
@@ -385,8 +393,8 @@ public final class DefaultHTTPClient: HTTPClient, Loggable {
385393

386394
private func finish() {
387395
switch state {
388-
case .initializing, .start:
389-
preconditionFailure("finish() called in `start` or `initializing` state")
396+
case let .start(continuation):
397+
continuation.resume(returning: .failure(HTTPError(kind: .cancelled)))
390398

391399
case let .stream(continuation, response, _):
392400
continuation.resume(returning: .success(response))
@@ -396,7 +404,7 @@ public final class DefaultHTTPClient: HTTPClient, Loggable {
396404
log(.error, "\(request.method) \(request.url) failed with: \(error.localizedDescription)")
397405
continuation.resume(returning: .failure(error))
398406

399-
case .finished:
407+
case .initializing, .finished:
400408
break
401409
}
402410

0 commit comments

Comments
 (0)