Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-2773] function abnormally releasing instance. #45377

Closed
swift-ci opened this issue Sep 27, 2016 · 14 comments
Closed

[SR-2773] function abnormally releasing instance. #45377

swift-ci opened this issue Sep 27, 2016 · 14 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software run-time crash Bug → crash: Swift code crashed during execution

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-2773
Radar rdar://problem/29687047
Original Reporter erica (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 4
Component/s Compiler
Labels Bug, Miscompile, RunTimeCrash
Assignee None
Priority Medium

md5: 67a6e66d0f886f367c56762144624056

cloned to:

  • SR-5861 [4.0] function abnormally releasing instance

is duplicated by:

  • SR-2863 Calling closures with inout parameter inside a generic function causes runtime error
  • SR-3017 Bad Access with Block
  • SR-3048 Memory corruption in closures taking instances of inout classes
  • SR-3155 Runtime segmentation fault

Issue Description:

See: https://gist.github.com/erica/1bb492d616370c5e8ae3383b140c41b4

import Foundation
public func with<T: AnyObject>(_ item: T, update: (inout T) throws -> Void) rethrows -> T {
    var this = item
    try update(&this)
    var ptr: Unmanaged<T>? = Unmanaged<T>.passRetained(this).autorelease(); defer { ptr = nil }
    return this
}

let p = Process()
let task3 = with(p) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}

let task4 = with(Process()) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}
print(task3)
print(task4)

If the silly `ptr` workaround is commented out, the second test (task4) fails. I've tested in Xcode and at the command line.

% swiftc test.swift
% ./test
<NSConcreteTask: 0x7fb531c0b200>
Segmentation fault
% swift test.swift
<NSConcreteTask: 0x7fad8b6cfbe0>
0  swift                    0x000000010d0a7b6d PrintStackTraceSignalHandler(void*) + 45
1  swift                    0x000000010d0a75b6 SignalHandler(int) + 470
2  libsystem_platform.dylib 0x00007fffce81fbba _sigtramp + 26
3  libsystem_platform.dylib 000000000000000000 _sigtramp + 830342240
4  swift                    0x000000010a9821b8 llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 456
5  swift                    0x000000010a98774b llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 763
6  swift                    0x000000010a4d3662 swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 3234
7  swift                    0x000000010a4be07e performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 23358
8  swift                    0x000000010a4b6265 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 17029
9  swift                    0x000000010a47382d main + 8685
10 libdyld.dylib            0x00007fffce613255 start + 1
11 libdyld.dylib            0x000000000000000c start + 832490936
Stack dump:
0.  Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret test.swift -target x86_64-apple-macosx10.9 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -color-diagnostics -module-name test 
Segmentation fault
% 
@swift-ci
Copy link
Collaborator Author

Comment by erica sadun (JIRA)

mikeash: erica: definite codegen bug, with a totally cut down example I see one retain and two releases
[12:59pm] mikeash: the retain is at the top of with, one release is at the end of the closure, and one is at the end of with
[12:59pm] mikeash: I'm guessing the one at the end of with shouldn't be there
[12:59pm] mikeash: if you want to see for yourself, stick breakpoints on 15/21 https://gist.github.com/mikeash/1d216d2badf7c2d4430dd4fda008e933

@belkadan
Copy link
Contributor

The retains and releases look correct to me; I think Mike missed Swift's +1 convention.

It looks like we drop the inout on the inferred type of $0 for some reason, leading to complete garbage. You can work around this by using an explicit signature for the closure (with in).

@belkadan
Copy link
Contributor

Oops, no, that's not exactly it. But the explicit signature does fix the problem, which is suspicious.

@belkadan
Copy link
Contributor

Ah, it's the reabstraction thunk for the closure-to-closure conversion because of the dropped inout.

// thunk
sil shared [transparent] [reabstraction_thunk] @_TTRXFo_oCSo7Process__XFo_lS__zoPs5Error__ : $@convention(thin) (@inout Process, @owned @callee_owned (@owned Process) -> ()) -> @error Error {
// %0                                             // user: %2
// %1                                             // user: %3
bb0(%0 : $*Process, %1 : $@callee_owned (@owned Process) -> ()):
  %2 = load %0 : $*Process, scope              // user: %3
  %3 = apply %1(%2) : $@callee_owned (@owned Process) -> (), scope
  %4 = tuple (), scope                         // user: %5
  return %4 : $(), scope                       // id: %5
}

There should be a retain of %2 before it's passed to the underlying closure. @slavapestov, does that sound right?

@belkadan
Copy link
Contributor

(i.e. Mike was right, and I should expect that by now)

@belkadan
Copy link
Contributor

belkadan commented Oct 5, 2016

Slava's on vacation at the moment. @jckarter?

@belkadan
Copy link
Contributor

I think we fixed this one on master. Not sure if it made it to 3.0.1.

@hujunfeng
Copy link

The bug still exists in Swift 3.0.2 (Xcode 8.2).

% swiftc --version
Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9
% cat with.swift
import Foundation
public func with<T: AnyObject>(_ item: T, update: (inout T) throws -> Void) rethrows -> T {
    var this = item
    try update(&this)
    // var ptr: Unmanaged<T>? = Unmanaged<T>.passRetained(this).autorelease(); defer { ptr = nil  }
    return this
}

let p = Process()
let task3 = with(p) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}

let task4 = with(Process()) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}
print(task3)
print(task4)
% swiftc with.swift
% ./with
<NSConcreteTask: 0x7f991440b1e0>
[1]    3082 segmentation fault  ./with
% swift with.swift                                                                                                                             139
<NSConcreteTask: 0x7fc29d5e5aa0>
0  swift                    0x000000010a2243ad PrintStackTraceSignalHandler(void*) + 45
1  swift                    0x000000010a223b56 SignalHandler(int) + 790
2  libsystem_platform.dylib 0x00007fffac857bba _sigtramp + 26
3  libsystem_platform.dylib 000000000000000000 _sigtramp + 1400538208
4  libsystem_platform.dylib 0x000000010bfa1242 _sigtramp + 1601476258
5  swift                    0x000000010771b6ab llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 459
6  swift                    0x00000001077210ab llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 763
7  swift                    0x00000001072472ef swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 3503
8  swift                    0x0000000107231dfe performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 23470
9  swift                    0x000000010722a2b3 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 17859
10 swift                    0x00000001071e65cf main + 8239
11 libdyld.dylib            0x00007fffac64a255 start + 1
Stack dump:
0.  Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret with.swift -target x86_64-apple-macosx10.9 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -color-diagnostics -module-name with
[1]    3094 segmentation fault  swift with.swift

@belkadan
Copy link
Contributor

Indeed, I'm seeing it on master again as well. Not sure what I checked before.

@belkadan
Copy link
Contributor

@swift-ci create

@hujunfeng
Copy link

Yay! `test.swift` no longer crashes in Swift 3.1 (Xcode 8.3 beta 2). Looks like the bug is finally fixed.

@DougGregor
Copy link
Member

Great!

@hujunfeng
Copy link

This piece of code crashes again in Swift 4 (Xcode 9 beta 6)

~/Desktop
> swift --version
Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36)
Target: x86_64-apple-macosx10.9
~/Desktop
> cat test.swift
import Foundation
public func with<T: AnyObject>(_ item: T, update: (inout T) throws -> Void) rethrows -> T {
    var this = item
    try update(&this)
    return this
}

let p = Process()
let task3 = with(p) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}

let task4 = with(Process()) {
    $0.launchPath = "/usr/bin/mdfind"
    $0.arguments = ["kMDItemDisplayName == *.playground"]
    $0.standardOutput = pipe
}
print(task3)
print(task4)
~/Desktop
> swiftc test.swift
~/Desktop
> ./test
<NSConcreteTask: 0x7fef3740b330>
fish: './test' terminated by signal SIGSEGV (Address boundary error)

@belkadan
Copy link
Contributor

belkadan commented Sep 8, 2017

I'll clone a new bug for it, then.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software run-time crash Bug → crash: Swift code crashed during execution
Projects
None yet
Development

No branches or pull requests

5 participants