Skip to content

Commit c5dab03

Browse files
committed
[TSan] Add positive test for TSan + Dispatch on Linux
1) Enable tests that use `import Dispatch` on Linux. Add substitution `%import-libdispatch` that needs to be used for all cross-platform tests (i.e., tests that are intended to be run on other platforms than Darwin) that do `import Dispatch` or enable thread sanitizer. 2) Make sure as many existing Dispatch and TSan tests as possible run on Linux. Mark tests that would require substantial work with `UNSUPPORTED: OS=linux-gnu`. 3) Add test that shows that TSan finds a simple race when using `Dispatch.async` incorrectly. The real test suite for TSan's libdispatch support lives in the LLVM/compiler-rt side. Add `%deflake` substitution for deflake utility. rdar://problem/49177535
1 parent 14a20ee commit c5dab03

20 files changed

+138
-88
lines changed

test/ClangImporter/Dispatch_test.swift

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-typecheck-verify-swift
22

33
// REQUIRES: libdispatch
4+
// UNSUPPORTED: OS=linux-gnu
45

56
import Dispatch
67

test/IRGen/tsan-attributes.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
// RUN: %target-swift-frontend -emit-ir -sanitize=thread %s | %FileCheck %s -check-prefix=TSAN
44

5-
// TSan is currently only supported on 64 bit mac and simulators.
6-
// (We do not test the simulators here.)
7-
// REQUIRES: CPU=x86_64, OS=macosx
5+
// TSan is only supported on 64 bit.
6+
// REQUIRES: PTRSIZE=64
87

98
// TSAN: define {{.*}} @"$s4main4testyyF"() [[DEFAULT_ATTRS:#[0-9]+]]
109
public func test() {

test/IRGen/tsan_coroutines.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// This test case used to crash when tsan ran before co-routine lowering.
22
// RUN: %target-swift-frontend -emit-ir -sanitize=thread %s | %FileCheck %s
33

4-
// TSan is currently only supported on 64 bit mac and simulators.
5-
// (We do not test the simulators here.)
6-
// REQUIRES: CPU=x86_64, OS=macosx
4+
// TSan is only supported on 64 bit.
5+
// REQUIRES: PTRSIZE=64
76

87
public class C { }
98

@@ -23,7 +22,7 @@ extension Foobar {
2322
}
2423

2524
// We used to crash emitting the subscript function.
26-
// CHECK: define swiftcc { i8*, %T15tsan_coroutines1CC* } @"$s15tsan_coroutines6FoobarVyAA1CCAC5IndexVcir"
25+
// CHECK: define {{(protected)?}} swiftcc { i8*, %T15tsan_coroutines1CC* } @"$s15tsan_coroutines6FoobarVyAA1CCAC5IndexVcir"
2726
@_borrowed
2827
public subscript(position: Index) -> C {
2928
return things.values[position.myIndex]

test/Profiler/instrprof_tsan.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-swift-frontend -emit-ir -profile-generate -sanitize=thread %s | %FileCheck %s
22

3-
// REQUIRES: OS=macosx
4-
// REQUIRES: CPU=x86_64
3+
// TSan is only supported on 64 bit.
4+
// REQUIRES: PTRSIZE=64
55

66
// CHECK: define {{.*}}empty
77
// CHECK-NOT: load{{.*}}empty

test/Sanitizers/tsan-emptyarraystorage.swift

+12-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread -o %t_tsan-binary
1+
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread %import-libdispatch -o %t_tsan-binary
22
// RUN: %target-codesign %t_tsan-binary
33
// RUN: %target-run %t_tsan-binary 2>&1 | %FileCheck %s
44
// REQUIRES: executable_test
@@ -9,29 +9,22 @@
99
// don't support TSan.
1010
// UNSUPPORTED: remote_run
1111

12-
import Foundation
12+
import Dispatch
1313

1414
let sem = DispatchSemaphore(value: 0)
15+
let q1 = DispatchQueue(label: "q1")
16+
let q2 = DispatchQueue(label: "q2")
1517

16-
class T1: Thread {
17-
override func main() {
18-
var oneEmptyArray: [[String:String]] = []
19-
oneEmptyArray.append(contentsOf: [])
20-
sem.signal()
21-
}
18+
q1.async {
19+
var oneEmptyArray: [[String:String]] = []
20+
oneEmptyArray.append(contentsOf: [])
21+
sem.signal()
2222
}
23-
let t1 = T1()
24-
t1.start()
25-
26-
class T2: Thread {
27-
override func main() {
28-
var aCompletelyUnrelatedOtherEmptyArray: [[Double:Double]] = []
29-
aCompletelyUnrelatedOtherEmptyArray.append(contentsOf: [])
30-
sem.signal()
31-
}
23+
q2.async {
24+
var aCompletelyUnrelatedOtherEmptyArray: [[Double:Double]] = []
25+
aCompletelyUnrelatedOtherEmptyArray.append(contentsOf: [])
26+
sem.signal()
3227
}
33-
let t2 = T2()
34-
t2.start()
3528

3629
sem.wait()
3730
sem.wait()
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread %import-libdispatch -o %t_tsan-binary
2+
// RUN: %target-codesign %t_tsan-binary
3+
// RUN: not %target-run %t_tsan-binary 2>&1 | %FileCheck %s
4+
// REQUIRES: executable_test
5+
// REQUIRES: tsan_runtime
6+
// UNSUPPORTED: OS=tvos
7+
8+
// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs
9+
// don't support TSan.
10+
// UNSUPPORTED: remote_run
11+
12+
// Test ThreadSanitizer execution end-to-end with libdispatch.
13+
14+
import Dispatch
15+
16+
let sem = DispatchSemaphore(value: 0)
17+
let q = DispatchQueue.global(qos: .default)
18+
19+
var racy = 1
20+
21+
for _ in 1...1000 {
22+
q.async {
23+
racy = 2
24+
sem.signal()
25+
}
26+
q.async {
27+
racy = 3
28+
sem.signal()
29+
}
30+
}
31+
32+
for _ in 1...2000 {
33+
sem.wait()
34+
}
35+
36+
// CHECK: ThreadSanitizer: data race

test/Sanitizers/tsan-norace-block-release.swift

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1-
// RUN: %target-swiftc_driver %s -g -sanitize=thread -target %sanitizers-target-triple -o %t_tsan-binary
1+
// RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -target %sanitizers-target-triple -o %t_tsan-binary
22
// RUN: %target-codesign %t_tsan-binary
3-
// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s
3+
// RUN: %target-run %t_tsan-binary 2>&1 | %FileCheck %s
44
// REQUIRES: executable_test
5-
// REQUIRES: objc_interop
65
// REQUIRES: tsan_runtime
76

87
// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs
98
// don't support TSan.
109
// UNSUPPORTED: remote_run
1110

1211
// Test that we do not report a race on block release operation.
13-
import Foundation
14-
15-
public class Sad : NSObject {
12+
import Dispatch
13+
#if canImport(Darwin)
14+
import Darwin
15+
#elseif canImport(Glibc)
16+
import Glibc
17+
#else
18+
#error("Unsupported platform")
19+
#endif
20+
21+
public class Sad {
1622
private var _source: DispatchSourceTimer?
17-
public override init() {
23+
public init() {
1824
_source = DispatchSource.makeTimerSource()
1925

2026
// If this line is commented out no data race.
2127
_source?.setEventHandler(handler: globalFuncHandler)
2228

23-
super.init()
2429
_source?.resume()
2530
}
2631
deinit {
@@ -40,4 +45,3 @@ sleep(1)
4045
print("Done.")
4146

4247
// CHECK: Done.
43-
// CHECK-NOT: ThreadSanitizer: data race

test/Sanitizers/tsan-norace-deinit-run-time.swift

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
// RUN: %target-swiftc_driver %s -g -sanitize=thread -target %sanitizers-target-triple -o %t_tsan-binary
1+
// RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -target %sanitizers-target-triple -o %t_tsan-binary
22
// RUN: %target-codesign %t_tsan-binary
3-
// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s
3+
// RUN: %target-run %t_tsan-binary 2>&1 | %FileCheck %s
44
// REQUIRES: executable_test
5-
// REQUIRES: objc_interop
65
// REQUIRES: tsan_runtime
76

87
// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs
98
// don't support TSan.
109
// UNSUPPORTED: remote_run
1110

1211
// Test that we do not report a race on deinit; the synchronization is guaranteed by runtime.
13-
import Foundation
14-
15-
public class TestDeallocObject : NSObject {
12+
import Dispatch
13+
#if canImport(Darwin)
14+
import Darwin
15+
#elseif canImport(Glibc)
16+
import Glibc
17+
#else
18+
#error("Unsupported platform")
19+
#endif
20+
21+
public class TestDeallocObject {
1622
public var v : Int
17-
public override init() {
23+
public init() {
1824
v = 1
1925
}
2026

@@ -33,7 +39,7 @@ public class TestDeallocObject : NSObject {
3339
}
3440
}
3541

36-
if (true) {
42+
do {
3743
var tdo : TestDeallocObject = TestDeallocObject()
3844
tdo.accessMember()
3945

@@ -52,4 +58,3 @@ if (true) {
5258
print("Done.")
5359

5460
// CHECK: Done.
55-
// CHECK-NOT: ThreadSanitizer: data race

test/Sanitizers/tsan.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread -o %t_tsan-binary
1+
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread %import-libdispatch -o %t_tsan-binary
22
// RUN: %target-codesign %t_tsan-binary
33
// RUN: not env %env-TSAN_OPTIONS="abort_on_error=0" %target-run %t_tsan-binary 2>&1 | %FileCheck %s
44
// REQUIRES: executable_test

test/lit.cfg

+22-26
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,10 @@ if run_vendor == 'apple':
656656
config.target_codesign = "codesign -f -s -"
657657
config.target_runtime = "objc"
658658

659+
config.available_features.add('libdispatch')
660+
config.available_features.add('foundation')
661+
config.available_features.add('objc_interop')
662+
659663
xcrun_prefix = (
660664
"xcrun --toolchain %s --sdk %r" %
661665
(config.darwin_xcrun_toolchain, config.variant_sdk))
@@ -905,6 +909,16 @@ elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'wi
905909
config.target_sdk_name = "linux"
906910
config.target_runtime = "native"
907911
config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
912+
913+
config.libdispatch_build_dir = make_path(config.swift_obj_root, os.pardir,
914+
'libdispatch%s' % config.variant_suffix, 'src')
915+
if os.path.exists(config.libdispatch_build_dir):
916+
config.available_features.add('libdispatch')
917+
source_dir = make_path(config.swift_src_root, os.pardir, 'swift-corelibs-libdispatch')
918+
swift_module_dir = make_path(config.libdispatch_build_dir, 'swift')
919+
config.import_libdispatch = ('-I %s -I %s -L %s'
920+
% (source_dir, swift_module_dir, config.libdispatch_build_dir))
921+
908922
config.target_build_swift = (
909923
'%s -target %s %s %s %s %s %s'
910924
% (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt,
@@ -1214,7 +1228,7 @@ runtime_libs = {
12141228
'fuzzer': 'fuzzer_runtime'
12151229
}
12161230

1217-
if run_ptrsize != "32":
1231+
if run_ptrsize != "32" and 'libdispatch' in config.available_features:
12181232
runtime_libs['tsan'] = 'tsan_runtime'
12191233

12201234
check_runtime_libs(runtime_libs)
@@ -1312,14 +1326,15 @@ if os.path.exists(static_libswiftCore_path):
13121326
# default Swift tests to use the just-built libraries
13131327
target_stdlib_path = platform_module_dir
13141328
if not kIsWindows:
1329+
libdispatch_path = getattr(config, 'libdispatch_build_dir', '')
13151330
if 'use_os_stdlib' not in lit_config.params:
13161331
lit_config.note('Testing with the just-built libraries at ' + target_stdlib_path)
13171332
config.target_run = (
13181333
"/usr/bin/env "
13191334
"DYLD_LIBRARY_PATH='{0}' " # Apple option
1320-
"LD_LIBRARY_PATH='{0}' " # Linux option
1335+
"LD_LIBRARY_PATH='{0}:{1}' " # Linux option
13211336
"SIMCTL_CHILD_DYLD_LIBRARY_PATH='{0}' " # Simulator option
1322-
.format(target_stdlib_path)) + config.target_run
1337+
.format(target_stdlib_path, libdispatch_path)) + config.target_run
13231338
else:
13241339
os_stdlib_path = ''
13251340
if run_vendor == 'apple':
@@ -1330,9 +1345,9 @@ if not kIsWindows:
13301345
config.target_run = (
13311346
"/usr/bin/env "
13321347
"DYLD_LIBRARY_PATH='{0}' " # Apple option
1333-
"LD_LIBRARY_PATH='{0}' " # Linux option
1348+
"LD_LIBRARY_PATH='{0}:{1}' " # Linux option
13341349
"SIMCTL_CHILD_DYLD_LIBRARY_PATH='{0}' " # Simulator option
1335-
.format(all_stdlib_path)) + config.target_run
1350+
.format(all_stdlib_path, libdispatch_path)) + config.target_run
13361351

13371352
if not getattr(config, 'target_run_simple_swift', None):
13381353
config.target_run_simple_swift_parameterized = \
@@ -1376,7 +1391,7 @@ if not getattr(config, 'target_run_simple_swift', None):
13761391
% (config.target_build_swift, mcp_opt, config.target_codesign, config.target_run))
13771392

13781393
#
1379-
# When changing substitutions, update docs/Testing.rst.
1394+
# When changing substitutions, update docs/Testing.md.
13801395
#
13811396

13821397
config.substitutions.append(('%target-runtime', config.target_runtime))
@@ -1498,6 +1513,7 @@ config.substitutions.append(('%FileCheck',
14981513
config.filecheck,
14991514
'--enable-windows-compatibility' if kIsWindows else '')))
15001515
config.substitutions.append(('%raw-FileCheck', pipes.quote(config.filecheck)))
1516+
config.substitutions.append(('%import-libdispatch', getattr(config, 'import_libdispatch', '')))
15011517

15021518
if config.lldb_build_root != "":
15031519
config.available_features.add('lldb')
@@ -1526,25 +1542,5 @@ if platform.system() == 'Linux':
15261542
config.available_features.add("LinuxDistribution=" + distributor + '-' + release)
15271543
lit_config.note('Running tests on %s-%s' % (distributor, release))
15281544

1529-
if run_vendor == 'apple':
1530-
config.available_features.add('libdispatch')
1531-
config.available_features.add('foundation')
1532-
config.available_features.add('objc_interop')
1533-
else:
1534-
# TODO(yln): Works with the packaged swift distribution, but not during build.
1535-
# We need to make libdispatch/foundation available in the test resource directory
1536-
# or pass along the proper library include paths in the compiler invocations that are used
1537-
# to build the tests.
1538-
def has_lib(name):
1539-
return False
1540-
1541-
if has_lib('dispatch'):
1542-
config.available_features.add('libdispatch')
1543-
else:
1544-
# TSan runtime requires libdispatch on non-Apple platforms
1545-
config.available_features.discard('tsan_runtime')
1546-
1547-
if has_lib('Foundation'):
1548-
config.available_features.add('foundation')
15491545

15501546
lit_config.note("Available features: " + ", ".join(sorted(config.available_features)))

test/stdlib/Dispatch.swift

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-run-simple-swift
22
// REQUIRES: executable_test
33
// REQUIRES: libdispatch
4+
// UNSUPPORTED: OS=linux-gnu
45

56
import Dispatch
67
import StdlibUnittest

test/stdlib/DispatchData.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -swift-version 4 %s -o %t/a.out-4 && %target-codesign %t/a.out-4 && %target-run %t/a.out-4
3-
// RUN: %target-build-swift -swift-version 4.2 %s -o %t/a.out-4.2 && %target-codesign %t/a.out-4.2 && %target-run %t/a.out-4.2
2+
// RUN: %target-build-swift -swift-version 4 %s %import-libdispatch -o %t/a.out-4 && %target-codesign %t/a.out-4 && %target-run %t/a.out-4
3+
// RUN: %target-build-swift -swift-version 4.2 %s %import-libdispatch -o %t/a.out-4.2 && %target-codesign %t/a.out-4.2 && %target-run %t/a.out-4.2
44
// REQUIRES: executable_test
55
// REQUIRES: libdispatch
66

@@ -22,11 +22,12 @@ DispatchAPI.test("dispatch_data_t deallocator") {
2222
let q = DispatchQueue(label: "dealloc queue")
2323
var t = 0
2424

25-
autoreleasepool {
25+
do {
2626
let size = 1024
2727
let p = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
2828
let _ = DispatchData(bytesNoCopy: UnsafeBufferPointer(start: p, count: size), deallocator: .custom(q, {
2929
t = 1
30+
p.deallocate();
3031
}))
3132
}
3233

test/stdlib/DispatchDeprecationMacOS.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// RUN: %swift -typecheck -target x86_64-apple-macosx10.9 -verify -sdk %sdk %s
22
// REQUIRES: OS=macosx
3-
// REQUIRES: objc_interop
3+
// REQUIRES: libdispatch
44

5-
import Foundation
65
import Dispatch
76

87
// Don't warn because these APIs were deprecated in macOS 10.10 and the

test/stdlib/DispatchDeprecationWatchOS.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// RUN: %swift -typecheck -target i386-apple-watchos2.0 -verify -sdk %sdk %s
22
// REQUIRES: CPU=i386, OS=watchos
3-
// REQUIRES: objc_interop
3+
// REQUIRES: libdispatch
44

5-
import Foundation
65
import Dispatch
76

87
// These are deprecated on all versions of watchOS.

0 commit comments

Comments
 (0)