<!--
{
  "availability" : [
    "macOS: 26.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "FSKit",
  "identifier" : "/documentation/FSKit/FSTask/cancellationHandler",
  "metadataVersion" : "0.1.0",
  "role" : "Instance Property",
  "symbol" : {
    "kind" : "Instance Property",
    "modules" : [
      "FSKit"
    ],
    "preciseIdentifier" : "c:objc(cs)FSTask(py)cancellationHandler"
  },
  "title" : "cancellationHandler"
}
-->

# cancellationHandler

A handler called by FSKit upon canceling the task.

```
var cancellationHandler: (@Sendable () -> (any Error)?)? { get set }
```

## Discussion

FSKit calls the cancellation handler within an independent execution context.

If the handler can’t complete its work successfully, it can return an error from the block or closure.
FSKit logs any returned error and then terminates all activity in the container.

The task object clears its `cancellationHandler` property after the task’s cancellation or completion.
This helps accelerate the cleanup of retained state.

The exact structuring of the completion handler depends on the structuring of the code implementing the task.
As a concrete example, consider a check operation with the following class:

```swift
class YourFileSystem {
    let work_group: dispatch_group_t = DispatchGroup()
    var interrupted: Bool = false
    private lazy var leaveWorkGroupOnce = leaveWorkGroup()
}
```

and a `startCheckWithTask` method with a helper method `performCheck` like the following:

```swift
func performCheck(task: FSTask, progress: Progress,
                  context: YourFileSystemCancelationContext) {
   // See discussion for notes on implementing this method.
}

func startCheck(task: FSTask, options: FSTaskOptions) throws -> Progress {
    let someQueue = DispatchQueue.global()
    let progress = Progress()
    let checkContext = YourFileSystemCancelationContext()
    checkContext.work_group.enter()
    task.cancellationHandler = {
        checkContext.interrupted = true
        checkContext.work_group.wait()
        return nil
    }
    someQueue.async {
        self.performCheck(task: task, progress: progress, context:checkContext)
    }
    return progress
}
```

When canceled, the handler block in this example sets the checker’s `interrupted` property, and then calls the <doc://com.apple.documentation/documentation/Dispatch/DispatchGroup> method <doc://com.apple.documentation/documentation/Dispatch/DispatchGroup/wait()> (Swift) or the function <doc://com.apple.documentation/documentation/Dispatch/dispatch_group_wait> (Objective-C) on the checker’s work group.
Because neither of these operations can fail, the handler returns `nil` to indicate it didn’t encounter an error.

For simplicity, this example doesn’t account for errors, whereas production code must do so.
Furthermore, when fully implemented, the `performCheck` method should perform a check operation.
Specifically, it should periodically update the progress object and check its `interrupted` variable.
The check can either complete successfully, complete with an error, or enter the interrupted state.
It should then call [`didComplete(error:)`](/documentation/FSKit/FSTask/didComplete(error:)) with the appropriate error value or `nil`.
Finally it should call `context.work_group.leave()` (Swift) or `dispatch_group_leave(context.work_group)` (Objective-C) to remove itself from its dispatch group.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)