SwiftLint
SwiftLint copied to clipboard
Bus error
New Issue Checklist
- [x] Updated SwiftLint to the latest version
- [x] I searched for existing GitHub issues
Describe the bug
swiftlint lint
exits with a bus error when run on my machine, similar to #2391. It happens to me reliably.
See some investigation in the comments below.
Complete output when running SwiftLint, including the stack trace and command used
$ git clone https://github.com/signalapp/Signal-iOS.git
# ...
$ cd Signal-iOS
$ swiftlint lint
# ...lints some files...
# zsh: bus error swiftlint lint
This also happens with swiftlint lint --quiet
and swiftlint lint --no-cache
.
The example output is lengthy, but nondeterministic (as far as I can tell).
There isn't an obvious stack trace. (EDIT: See below for a stack trace.)
Environment
- SwiftLint version: 0.47.1
- Installation method used: Homebrew
- Paste your configuration file: public here
- Are you using nested configurations? No
- Which Xcode version are you using (check
xcodebuild -version
)? Xcode 13.4, Build version 13F17a
I was able to get a stack trace when running it in Xcode.
-
The error seems to reliably happen on this line in SourceKitten.
-
The stack trace makes me think it's caught in some kind of loop, because the trace is quite deep.
-
The error isn't obviously deterministic. In other words, it doesn't seem to happen with the same files each time. Here are the last lines printed before the crash for a few runs:
Linting 'DeviceTransferOperation.swift' (686/1103)
Linting 'DeviceTransferService+State.swift' (683/1103)
Linting 'DeviceTransferService+Manifest.swift' (88/1103)
Linting 'DeviceTransferService+State.swift' (683/1103)
Linting 'AppUpdateNag.swift' (685/1094)
Linting 'EmojiWithSkinTones+String.swift' (82/1093)
Other than the two that died at ~85, the rest seem to happen at roughly the same time. Not sure what that means, if anything.
I don't know enough about this project and SourceKitten to know what's next, but I hope this investigation helps.
I was able to repro it.
I'm pretty sure EmojiWithSkinTones+String.swift
is the file triggering this. SourceKit chokes on it:
➜ Signal-iOS git:(main) sourcekitten syntax --file Signal/src/util/Emoji/EmojiWithSkinTones+String.swift
sourcekit: [1:connection-event-handler:7427: 0.0000] Connection interruptsourcekit: [1:updateSemanticEditorDelay:7427: 0.0003] disabling semantic editor for 10 secondssourcekit: [1:pingService:7427: 0.0003] pinging servicesourcekitten: connection to SourceKitService restored!
Error: Connection interrupted
While debugging locally, I get a crash (looks like a stack overflow) inside SwiftSyntax:
![Screen Shot 2022-06-07 at 11 58 59 PM](https://user-images.githubusercontent.com/833072/172552294-468e8ef1-8078-45c6-a487-d5e9e639a5bd.png)
Hardcoding commandsCache
to return []
in SwiftLintFile+Cache
crash for me (although SourceKit still chokes on that file). It'd be great to extract confirm in a sample app that SwiftSyntax crashes with this file and file an issue.
Here's some additional info just to help with the possible investigation of the issue.
I was able to reproduce a similar crash with the same "bus error" message by running SwiftLint v 0.47.0 on an M1 Mac using SwiftPM (swift run swiftlint
).
Here's a minimal file that triggered the crash:
import SwiftUI
struct CrashSwiftLint: View {
var body: some View {
VStack {
VStack {
VStack {
VStack {
Text("test")
.padding()
.padding()
.padding()
.padding()
.padding()
.padding()
.padding()
.padding()
}
}
}
}
}
}
However, swift run swiftlint
builds the binary in debug configuration.
When I run SwiftLint in release configuration using swift run -c release swiftlint
, it no longer crashes.
Hope that helps.
is there any update on this? running SwiftLint in release configuration results in whole module optimization being used, so we get no benefits of incremental compilation, and build times are thusly incredibly long. any alternatives? consuming SwiftLint via SPM is amazing for aligning team versioning, and I'd rather not switch to using brew if possible
consuming SwiftLint via SPM is amazing for aligning team versioning, and I'd rather not switch to using brew if possible
I'm using the version from Homebrew and seeing this problem, so I'm not sure if switching to Homebrew will fix it. (But that might conflict with @vadimbelyaev's comment.)
@EvanHahn-Signal this issue seems to be resolved for me on SwiftLint v0.48.0, if you have time to verify I'd be intrigued to know if it works for you too
I just tried upgrading to SwiftLint 0.48.0 and still see a bus error, unfortunately.
I can reproduce this on 0.49.0 as well when running SwiftLint as a Swift executable binary. e.g. swift run swiftlint
SwiftLint will fail on a few different files in our project.
Trying to swift run sourcekitten syntax --file
on the failing files doesn't show any errors.
Anecdotally, I noticed it seems to dislike complex and nested ternary expressions (which would be a good target for refactoring anyways).
@nicorichard can you please share a sample file that triggers the crash?
As far as SwiftSyntax crashing in debug builds, that's a known issue. As far as I'm aware it doesn't happen in release builds.
SwiftSyntax in debug builds has massive stack frames, leading to stack overflows. Those are optimized away in release builds and not an issue from what I've seen.
I just tested on master
with the crashing file from https://github.com/realm/SwiftLint/issues/3988#issuecomment-1157395305 and it doesn't happen anymore in either debug or release:
$ bazel run -c dbg swiftlint -- Crash.swift
INFO: Invocation ID: f1a7c517-03e5-4af4-a0e9-90dada04c7c7
INFO: Build option --compilation_mode has changed, discarding analysis cache.
INFO: Analyzed target //:swiftlint (0 packages loaded, 1499 targets configured).
INFO: Found 1 target...
Target //:swiftlint up-to-date:
bazel-bin/swiftlint
INFO: Elapsed time: 61.623s, Critical Path: 61.21s
INFO: 66 processes: 32 internal, 22 darwin-sandbox, 12 worker.
INFO: Build completed successfully, 66 total actions
INFO: Build completed successfully, 66 total actions
Linting Swift files at paths Crash.swift
Linting 'Crash.swift' (1/1)
/Users/jsimard/src/SwiftLint/Crash.swift:1:1: warning: File Name Violation: File name should match a type or extension declared in the file (if any). (file_name)
Done linting! Found 1 violation, 0 serious in 1 file.
The failing code is in an extremely complex and dense file with lots of nesting collections calls (reduce, map) and ternaries. I think it's a little too dense and proprietary to my employer to post though.
Unfortunately, I could not replicate it by attempting to write a minimal reproducible example but after some light refactoring everything works..
Done linting! Found 90 violations, 0 serious in 2060 files.
Here's a reproducible example
[1] 43678 bus error swift run swiftlint lint
import SwiftUI
struct SimplifiedView<Label>: View where Label: View {
@Binding var step: Int
private let range: ClosedRange<Int>
private let label: Label
private let condition: Bool = false
public init(
step: Binding<Int>,
in range: ClosedRange<Int>,
@ViewBuilder label: () -> Label
) {
_step = step
self.range = range
self.label = label()
}
var body: some View {
HStack {
HStack {
Button(action: {}) {
if condition {
Text("")
} else {
Text("")
}
}
.rotationEffect(.degrees(360))
.buttonStyle(PlainButtonStyle())
.foregroundColor(.red)
.disabled(true)
}
.padding(.all, 8)
.background(Color.red)
.clipShape(Capsule())
label
}
.frame(maxWidth: .infinity, maxHeight: 40, alignment: .trailing)
.animation(.easeInOut, value: step)
}
}
even the simplest changes, like commenting out a single line and this will lint.
@nicorichard what version of SwiftLint are you using? I just tried with the source code you posted and it runs fine on macOS:
$ swiftlint --enable-all-rules input.swift
Linting Swift files at paths input.swift
Linting 'input.swift' (1/1)
input.swift:4:14: warning: Explicit ACL Violation: All declarations should specify Access Control Level keywords explicitly. (explicit_acl)
input.swift:20:5: warning: Explicit ACL Violation: All declarations should specify Access Control Level keywords explicitly. (explicit_acl)
input.swift:3:1: warning: Explicit ACL Violation: All declarations should specify Access Control Level keywords explicitly. (explicit_acl)
input.swift:3:1: warning: Explicit Top Level ACL Violation: Top-level declarations should specify Access Control Level keywords explicitly. (explicit_top_level_acl)
input.swift:1:1: warning: File Name Violation: File name should match a type or extension declared in the file (if any). (file_name)
input.swift:10:12: warning: Lower ACL than parent Violation: Ensure definitions have a lower access control level than their enclosing parent (lower_acl_than_parent)
input.swift:23:36: warning: Multiple Closures with Trailing Closure Violation: Trailing closure syntax should not be used when passing more than one closure argument. (multiple_closures_with_trailing_closure)
input.swift:8:26: warning: Redundant Type Annotation Violation: Variables should not have redundant type annotation (redundant_type_annotation)
input.swift:44:1: warning: Trailing Newline Violation: Files should have a single trailing newline. (trailing_newline)
input.swift:10:12: warning: Type Contents Order Violation: An 'initializer' should not be placed amongst the type content(s) 'instance_property'. (type_contents_order)
Done linting! Found 10 violations, 0 serious in 1 file.
$ swiftlint version
0.49.1
$ swift run swiftlint version
Building for debugging...
Build complete! (0.12s)
0.49.1
You must run SwiftLint via Swift Package Manager using swift run
for the error to occur.
You must run SwiftLint via Swift Package Manager using
swift run
for the error to occur.
As I previously said:
SwiftSyntax in debug builds has massive stack frames, leading to stack overflows. Those are optimized away in release builds and not an issue from what I've seen.
To avoid these stack overflows, please run SwiftLint compiled with -c release
when using SwiftPM or with --config=release
when using Bazel, or just use the prebuilt release binaries.