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-585] Segfault on Linux in code using "catch let error as NSError" #43202

Closed
swift-ci opened this issue Jan 19, 2016 · 19 comments
Closed

[SR-585] Segfault on Linux in code using "catch let error as NSError" #43202

swift-ci opened this issue Jan 19, 2016 · 19 comments

Comments

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Jan 19, 2016

Previous ID SR-585
Radar rdar://problem/30766599
Original Reporter rothomp3 (JIRA User)
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Ubuntu Linux 15.10
LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift e25cd88

Additional Detail from JIRA
Votes 8
Component/s Compiler
Labels Bug, RunTimeCrash, Runtime
Assignee rothomp3 (JIRA)
Priority Medium

md5: f2030dd3a4949c21dd4280ad4f13922d

is duplicated by:

  • SR-3565 SIGSEGV: invalid address constructing AnyError from NSError
  • SR-1380 NSFileManager.moveItem(atPath:toPath:) segfaults on Ubuntu 15.10

relates to:

  • SR-1547 NSData causes segmentation fault

Issue Description:

Short example to reproduce the problem:

import Foundation

do {
    throw NSError(domain: "com.mydomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "an error!"])
} catch let error as NSError {
    print(error.userInfo)
}

Backtrace from "swift errortest.swift":

#​0 0x0000000003042448 llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/home/robert/swift/usr/bin/swift+0x3042448)
#​1 0x0000000003040c46 llvm::sys::RunSignalHandlers() (/home/robert/swift/usr/bin/swift+0x3040c46)
#​2 0x0000000003042f76 SignalHandler(int) (/home/robert/swift/usr/bin/swift+0x3042f76)
#​3 0x00007fa62486ad10 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10d10)
#​4 0x00007fa621bb2eb7 swift_dynamicCast (/home/robert/swift/usr/lib/swift/linux/libswiftCore.so+0x2fceb7)
#​5 0x00007fa624c7b1b2
#&#8203;6 0x0000000000d1f6c4 llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) (/home/robert/swift/usr/bin/swift+0xd1f6c4)
#&#8203;7 0x0000000000d22ccf llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, char const* const*) (/home/robert/swift/usr/bin/swift+0xd22ccf)
#&#8203;8 0x0000000000bfd338 swift::RunImmediately(swift::CompilerInstance&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) (/home/robert/swift/usr/bin/swift+0xbfd338)
#&#8203;9 0x00000000007775d4 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&) (/home/robert/swift/usr/bin/swift+0x7775d4)
#&#8203;10 0x0000000000772b89 frontend_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/robert/swift/usr/bin/swift+0x772b89)
#&#8203;11 0x000000000076e276 main (/home/robert/swift/usr/bin/swift+0x76e276)
#&#8203;12 0x00007fa6231f0a40 __libc_start_main /build/buildd/glibc-2.21/csu/libc-start.c:323:0
#&#8203;13 0x000000000076d799 _start (/home/robert/swift/usr/bin/swift+0x76d799)
Stack dump:
0.  Program arguments: /home/robert/swift/usr/bin/swift -frontend -interpret ./errortest.swift -target x86_64-unknown-linux-gnu -disable-objc-interop -module-name errortest 
@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 15, 2016

Comment by John Endres (JIRA)

A note here. This crash seems to be specific to catching NSError. When throwing something based off of the ErrorType protocol, the crash does not happen.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 18, 2016

Comment by Vadim Eisenberg (JIRA)

The problem seems to be due to the fact that in the swift-corelibs-foundation NSError does not implement ErrorType: https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSError.swift

While https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/NSError.swift provides an extension that does:
extension NSError : ErrorType {
public var _domain: String { return domain }
public var _code: Int { return code }
}

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 18, 2016

Comment by Robert Thompson (JIRA)

vadim (JIRA User) Check further down in the file,

extension NSError : ErrorType { }

on line 168 😉

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 18, 2016

Comment by Vadim Eisenberg (JIRA)

rothomp3 (JIRA User) Oops. So the bug is not so simple to fix 🙂

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Mar 13, 2016

Comment by John Brownlee (JIRA)

I wrote a test case for this and ran it in a debugger, and got the following backtrace:

  • thread #1: tid = 17831, 0x00007ffff7aa7567 libswiftCore.so`swift::ValueWitnessFlags::getAlignmentMask(this=0x0074666977732f02) const + 23 at Metadata.h:237, name = 'TestFoundation', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)

  • frame #0: 0x00007ffff7aa7567 libswiftCore.so`swift::ValueWitnessFlags::getAlignmentMask(this=0x0074666977732f02) const + 23 at Metadata.h:237
    frame #1: 0x00007ffff7aa753c libswiftCore.so`swift::ValueWitnessTable::getAlignmentMask(this=0x0074666977732e72) const + 28 at Metadata.h:741
    frame #2: 0x00007ffff7aa7388 libswiftCore.so`swift::SwiftError::getValue(this=0x000000000090b9e0) const + 104 at ErrorObject.h:103
    frame #3: 0x00007ffff7aa1cd4 libswiftCore.so`_dynamicCastToUnknownClassFromExistential(dest=0x00007fffffffd3a0, src=0x00007fffffffd3a8, srcType=0x00007ffff7fe0190, targetType=0x00007ffff770bbf8, flags=Default) + 356 at Casting.cpp:1519
    frame #4: 0x00007ffff7aa1435 libswiftCore.so`swift_dynamicCast(dest=0x00007fffffffd3a0, src=0x00007fffffffd3a8, srcType=0x00007ffff7fe0190, targetType=0x00007ffff770bbf8, flags=Default) + 613 at Casting.cpp:2111
    frame #5: 0x000000000047347e TestFoundation`TestNSError.test_catchingError(self=<unavailable>, $error=<unavailable>) throws -> () + 190 at TestNSError.swift:35
    frame #6: 0x0000000000473fea TestFoundation`partial apply + 26 at TestNSError.swift:0
    frame #7: 0x0000000000419c08 TestFoundation`thunk + 24 at TestNSAffineTransform.swift:0
    frame #8: 0x0000000000473f79 TestFoundation`partial apply for thunk + 89 at TestNSError.swift:0
    frame #9: 0x00007ffff6bfcc7f libXCTest.so`thunk + 47 at <unknown>:0

I think the error is getting introduced around line ErrorObject.h:103
unsigned alignMask = type->getValueWitnesses()->getAlignmentMask();

There's guards around that code to prevent it from being run on a "pure NSError", but the isPureNSError method always returns false on the Swift runtime. It looks to me like the NSErrors on the Swift runtime need to be treated as pure NSErrors for the purposes of this casting. Changing the logic in Casting.cpp:1516 in this way prevents the crash, but I don't know how to properly distinguish NSError from native Swift errors to provide a real implementation of isPureNSError.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Nov 13, 2016

Comment by Mark Woollard (JIRA)

I've been looking into an issue over in Foundation - SR-1547 - which led me here as its actually the same issue as here and nothing to do with NSData as that issue suggests. From what I've deduced so far when an NSError is thrown and caught its the same instance that is `error` in the catch but is now treated as an instance of SwiftError C++ class which NSError is not (code passes the NSError instance into swift::swift_getErrorValue as SwiftError) and it all falls apart ! lldb sees the caught error as just the Error protocol but seems compiler is making further assumption that its an instance of SwiftError. Only started working through the codebase this w/e having decided to get involved so still limited in understanding but this seems pretty fundamental issue for Linux? I also note that throwing the swift error wrappers such as POSIXError, CocoaError or URLError gets around the issue - should the compiler be doing this wrapping automatically?

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jan 11, 2017

Comment by Maksim Rogov (JIRA)

Also seeing this issue on Ubuntu 16.04, hope we can get a fix by 3.1. Crashing error handling is really hard to track down 🙂

Update: This is a serious bug as Swift is pretty much unusable on Linux due to this.

@gwynne
Copy link
Contributor

@gwynne gwynne commented Feb 22, 2017

Still seeing this in the latest snapshots and on master, it's wreaking all kind of havoc. A fix would be great 🙂

Backtrace looks like this these days:

* thread #&#8203;1, name = 'Test', stop reason = signal SIGSEGV: invalid address (fault address: 0x90)
  * frame #&#8203;0: libswiftCore.so`swift_dynamicCast [inlined] swift::ValueWitnessFlags::getAlignmentMask() const at Metadata.h:231
    frame #&#8203;1: libswiftCore.so`swift_dynamicCast [inlined] swift::ValueWitnessTable::getAlignmentMask(this=0x0000000000000000) const at Metadata.h:733
    frame #&#8203;2: libswiftCore.so`swift_dynamicCast [inlined] swift::SwiftError::getValue(this=0x00000000008bf920) const at ErrorObject.h:119
    frame #&#8203;3: libswiftCore.so`swift_dynamicCast at Casting.cpp:1508
    frame #&#8203;4: libswiftCore.so`swift_dynamicCast(dest=<unavailable>, src=<unavailable>, srcType=<unavailable>, targetType=0x00007ffff75d5ef8, flags=Default) at Casting.cpp:2510

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 22, 2017

Comment by AdamDann (JIRA)

I would also like to see a fix for this, thanks.

@gwynne
Copy link
Contributor

@gwynne gwynne commented Feb 24, 2017

New info - it crashes on ANY attempt to use an NSError value in any way, regardless of whether you attempt to treat it specifically as NSError or not.

@jckarter
Copy link
Member

@jckarter jckarter commented Feb 25, 2017

This should fix it: #7761

@jckarter
Copy link
Member

@jckarter jckarter commented Feb 25, 2017

Even with the fix, though, I'd say that using NSError at all on Linux isn't a great idea. We provide the NSError bridge on Apple ObjC platforms for compatibility so that Swift code can work with the more specific CocoaError etc. types. There's no bridge on Linux so using NSError in the corelibs implementation breaks compatibility with code that uses those types.

@gwynne
Copy link
Contributor

@gwynne gwynne commented Feb 25, 2017

I was finally able to get my build working with this fix and I can confirm I no longer crash on Linux!!!!

@jckarter
Copy link
Member

@jckarter jckarter commented Feb 26, 2017

Should be fixed in master now.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 27, 2017

Comment by Sergey Minakov (JIRA)

Will this fix be included into 3.1 version?

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Feb 27, 2017

Comment by Maksim Rogov (JIRA)

naithar (JIRA User) I sure hope so! Very necessary fix unless they fix corelibs-foundation on Linux for 3.1 instead (not to use NSError).

@ffried
Copy link
Contributor

@ffried ffried commented Feb 28, 2017

@jckarter Does this also fix SR-1380 and SR-3565? Seems like this could be the same underlying issue.

@jckarter
Copy link
Member

@jckarter jckarter commented Feb 28, 2017

@swift-ci create

@jckarter
Copy link
Member

@jckarter jckarter commented Mar 1, 2017

PR for 3.1: #7847

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants