Navigation Menu

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-7863] corelibs-foundation build system doesn't respect assertions flag #3683

Open
swift-ci opened this issue Jun 4, 2018 · 1 comment

Comments

@swift-ci
Copy link
Contributor

swift-ci commented Jun 4, 2018

Previous ID SR-7863
Radar None
Original Reporter gmilos (JIRA User)
Type Improvement

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Improvement
Assignee None
Priority Medium

md5: d033feae658f0a47f72a9c6f6189edef

Issue Description:

Most projects in the swift build respect assertions option passed to build-script:

https://github.com/apple/swift/blob/master/utils/build_swift/driver_arguments.py#L606-L662

corelibs-foundation does not.

One of the effects is that fatalError -s in Foundation don't contain stack-traces, making them more difficult to diagnose.

I'm attaching an example reproduction in the form of SwiftPM package:

root@6da7b92950a9:/tmp/AssertionRepro# swift run
Compile Swift Module 'AssertionRepro' (1 sources)
Linking ./.build/x86_64-unknown-linux/debug/AssertionRepro
250 bytes
Fatal error: failWithError is not yet implemented: file Foundation/NSCoder.swift, line 702
Illegal instruction

In comparison fatalError in the executable itself (build in Debug mode, which enables assertions) gives:

root@6da7b92950a9:/tmp/AssertionRepro# swift run
Compile Swift Module 'AssertionRepro' (1 sources)
Linking ./.build/x86_64-unknown-linux/debug/AssertionRepro
Fatal error: fail and print stack trace: file /tmp/AssertionRepro/Sources/AssertionRepro/main.swift, line 4
Current stack trace:
0    libswiftCore.so                    0x00007fe488fdc750 _swift_stdlib_reportFatalErrorInFile + 221
1    libswiftCore.so                    0x00007fe488cf30f0 <unavailable> + 1442032
2    libswiftCore.so                    0x00007fe488f836a2 <unavailable> + 4130466
3    libswiftCore.so                    0x00007fe488f84869 <unavailable> + 4135017
4    libswiftCore.so                    0x00007fe488cf2496 <unavailable> + 1438870
5    libswiftCore.so                    0x00007fe488f832fb <unavailable> + 4129531
6    libswiftCore.so                    0x00007fe488cf2496 <unavailable> + 1438870
7    libswiftCore.so                    0x00007fe488e8a679 <unavailable> + 3110521
8    libswiftCore.so                    0x00007fe488cf1ce0 _assertionFailure(_:_:file:line:flags:) + 44
9    AssertionRepro                     0x0000564e0ed4f4b9 <unavailable> + 9401
10   AssertionRepro                     0x0000564e0ed4eef2 <unavailable> + 7922
11   libc.so.6                          0x00007fe486f35dd0 __libc_start_main + 245
12   AssertionRepro                     0x0000564e0ed4ec39 <unavailable> + 7225
Illegal instruction

Which can be symbolicated as follows:

root@6da7b92950a9:/tmp/AssertionRepro# swift run 2>&1 | symbolicate-linux-fatal .build/debug/AssertionRepro
Fatal error: fail and print stack trace: file /tmp/AssertionRepro/Sources/AssertionRepro/main.swift, line 4
Current stack trace:
0    libswiftCore.so      0x00007f83eec1982d    _swift_stdlib_reportFatalErrorInFile + 221
1    libswiftCore.so      0x00007f83ee9300f0    closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 320
2    libswiftCore.so      0x00007f83eebc06a2    partial apply forwarder for closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 34
3    libswiftCore.so      0x00007f83eebc1869    closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Neverpartial apply forwarder with unmangled suffix ".694" + 9
4    libswiftCore.so      0x00007f83ee92f496    function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 54
5    libswiftCore.so      0x00007f83eebc02fb    partial apply forwarder for closure #&#8203;1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 203
6    libswiftCore.so      0x00007f83ee92f496    function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 54
7    libswiftCore.so      0x00007f83eeac7679    function signature specialization <Arg[1] = Exploded> of Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 137
8    libswiftCore.so      0x00007f83ee92ed0c    Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 44
9    AssertionRepro       0x000055eff9b734b9    AssertionRepro.failExplosively() -> () + 185 at main.swift:4
10   AssertionRepro       0x000055eff9b72ef2    main + 34 at main.swift:6
11   libc.so.6                          0x00007f83ecb72dd0 __libc_start_main + 245
12   AssertionRepro       0x000055eff9b72c39    _start + 41
@swift-ci
Copy link
Contributor Author

swift-ci commented Jun 5, 2018

Comment by Gregor Milos (Grzegorz Miłoś) (JIRA)

I reviewed the logic that controls whether backtraces are printed. Key test is done here:

https://github.com/apple/swift/blob/0747546bd7bef90039442343457d31257ca322be/stdlib/public/core/AssertCommon.swift#L65-L76

@inlinable // FIXME(sil-serialize-all)
@_transparent
internal
func _fatalErrorFlags() -> UInt32 {
  // The current flags are:
  // (1 << 0): Report backtrace on fatal error
#if os(iOS) || os(tvOS) || os(watchOS)
  return 0
#else
  return _isDebugAssertConfiguration() ? 1 : 0
#endif
}

_isDebugAssertConfiguration is implemented here:
https://github.com/apple/swift/blob/0747546bd7bef90039442343457d31257ca322be/stdlib/public/core/AssertCommon.swift#L22-L31

@inlinable // FIXME(sil-serialize-all)
@_transparent
public // @testable
func _isDebugAssertConfiguration() -> Bool {
  // The values for the assert_configuration call are:
  // 0: Debug
  // 1: Release
  // 2: Fast
  return Int32(Builtin.assert_configuration()) == 0
}

Buildin.assert_configuration() is a special built-in function, described here:
https://github.com/apple/swift/blob/0747546bd7bef90039442343457d31257ca322be/docs/SIL.rst#assertion-configuration

the logic is implemented here:
https://github.com/apple/swift/blob/0747546bd7bef90039442343457d31257ca322be/lib/Frontend/CompilerInvocation.cpp#L619-L644

  // Parse the assert configuration identifier.
  if (const Arg *A = Args.getLastArg(OPT_AssertConfig)) {
    StringRef Configuration = A->getValue();
    if (Configuration == "DisableReplacement") {
      Opts.AssertConfig = SILOptions::DisableReplacement;
    } else if (Configuration == "Debug") {
      Opts.AssertConfig = SILOptions::Debug;
    } else if (Configuration == "Release") {
      Opts.AssertConfig = SILOptions::Release;
    } else if (Configuration == "Unchecked") {
      Opts.AssertConfig = SILOptions::Unchecked;
    } else {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(Args), A->getValue());
      return true;
    }
  } else if (FEOpts.ParseStdlib) {
    // Disable assertion configuration replacement when we build the standard
    // library.
    Opts.AssertConfig = SILOptions::DisableReplacement;
  } else if (Opts.AssertConfig == SILOptions::Debug) {
    // Set the assert configuration according to the optimization level if it
    // has not been set by the -Ounchecked flag.
    Opts.AssertConfig =
        (IRGenOpts.shouldOptimize() ? SILOptions::Release : SILOptions::Debug);
  }

To summarise, there are three flags that control assert_configuration: -O, -assert-config and -parse-stdlib. I'd argue that the special handling that stdlib receives should extend to Foundation too.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
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

1 participant