[Distributed] thread-safety also for parameter type metadata

We had fixed this bug in https://github.com/swiftlang/swift/pull/79381
but missed to realize the same problem existed for parameters as well.

This corrects the swift_func_getParameterTypeInfo impl, and also removes
the entire "unsafe" method, we no longer use it anywhere.

Resolves rdar://146679254
This commit is contained in:
Konrad 'ktoso' Malawski
2025-04-26 21:23:54 +09:00
parent bc68466cd6
commit 284c060d0a
2 changed files with 65 additions and 50 deletions

View File

@@ -2907,25 +2907,6 @@ static NodePointer getParameterList(NodePointer funcType) {
return parameterContainer;
}
static const Metadata *decodeType(TypeDecoder<DecodedMetadataBuilder> &decoder,
NodePointer type) {
assert(type->getKind() == Node::Kind::Type);
auto builtTypeOrError = decoder.decodeMangledType(type);
if (builtTypeOrError.isError()) {
auto err = builtTypeOrError.getError();
char *errStr = err->copyErrorString();
err->freeErrorString(errStr);
return nullptr;
}
if (!builtTypeOrError.getType().isMetadata())
return nullptr;
return builtTypeOrError.getType().getMetadata();
}
SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_SPI
unsigned swift_func_getParameterCount(const char *typeNameStart,
@@ -3009,8 +2990,21 @@ swift_func_getParameterTypeInfo(
SubstGenericParametersFromMetadata substFn(genericEnv, genericArguments);
DecodedMetadataBuilder builder(
demangler,
// for each parameter (TupleElement), store it into the provided buffer
for (unsigned index = 0; index != typesLength; ++index) {
auto nodePointer = parameterList->getChild(index);
if (nodePointer->getKind() == Node::Kind::TupleElement) {
assert(nodePointer->getNumChildren() == 1);
nodePointer = nodePointer->getFirstChild();
}
assert(nodePointer->getKind() == Node::Kind::Type);
auto request = MetadataRequest(MetadataState::Complete);
auto typeInfoOrErr = swift_getTypeByMangledNode(
request, demangler, nodePointer,
/*arguments=*/genericArguments,
/*substGenericParam=*/
[&substFn](unsigned depth, unsigned index) {
return substFn.getMetadata(depth, index).Ptr;
@@ -3019,24 +3013,13 @@ swift_func_getParameterTypeInfo(
[&substFn](const Metadata *type, unsigned index) {
return substFn.getWitnessTable(type, index);
});
TypeDecoder<DecodedMetadataBuilder> decoder(builder);
// for each parameter (TupleElement), store it into the provided buffer
for (unsigned index = 0; index != typesLength; ++index) {
auto *parameter = parameterList->getChild(index);
if (parameter->getKind() == Node::Kind::TupleElement) {
assert(parameter->getNumChildren() == 1);
parameter = parameter->getFirstChild();
if (typeInfoOrErr.isError()) {
return -3; // Failed to decode a type.
}
assert(parameter->getKind() == Node::Kind::Type);
auto type = decodeType(decoder, parameter);
if (!type)
return -3; // Failed to decode a type.
types[index] = type;
auto typeInfo = typeInfoOrErr.getType();
types[index] = typeInfo.getMetadata();
} // end foreach parameter
return typesLength;

View File

@@ -1,8 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -target %target-swift-5.7-abi-triple %S/../Inputs/FakeDistributedActorSystems.swift
// RUN: %target-build-swift -module-name dist -target %target-swift-5.7-abi-triple -parse-as-library -j2 -parse-as-library -plugin-path %swift-plugin-dir -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %target-run %t/a.out
// RUN: %target-run %t/a.out PARAMETER_TYPE
// RUN: %target-run %t/a.out RETURN_TYPE
// REQUIRES: executable_test
// REQUIRES: concurrency
@@ -17,7 +18,6 @@
import Darwin
import Distributed
import FakeDistributedActorSystems
import Foundation
typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
@@ -1052,20 +1052,39 @@ struct BigGeneric<T>: Codable {
}
distributed actor D {
public distributed func getBigGeneric(_ value: BigGeneric<TypeXXXX>) {}
public distributed func getBigGeneric() -> BigGeneric<TypeXXXX> {
return BigGeneric()
}
return BigGeneric()
}
}
func attempt(n: Int) {
var fname = "$s4dist1DC13getBigGenericAA0cD0VyAA8Type\(n)VGyF"
func attempt(_ mode: Mode, n: Int) {
var funcName_returnType = "$s4dist1DC13getBigGenericAA0cD0VyAA8Type\(n)VGyF"
var funcName_param = "$s4dist1DC13getBigGenericyyAA0cD0VyAA8Type\(n)VGF"
func tryLookup() {
let t = fname.withUTF8 {
__getReturnTypeInfo($0.baseAddress!, UInt($0.count), nil, nil)
}
let t: (any Any.Type)? =
switch mode {
case .returnType:
funcName_returnType.withUTF8 {
__getReturnTypeInfo($0.baseAddress!, UInt($0.count), nil, nil)
}
case .paramType:
funcName_param.withUTF8 { nameBuf in
var type: Any.Type?
withUnsafeMutablePointer(to: &type) { typePtr in
let ret = __getParameterTypeInfo(nameBuf.baseAddress!, UInt(nameBuf.count), nil, nil, typePtr._rawValue, 1)
if ret != 1 {
fatalError("Decoded \(ret) parameters, expected 1")
}
}
return type
}
}
guard let t else {
print("couldn't look up type for: \(fname)")
print("couldn't look up type for mode: \(mode)")
exit(1)
}
func examineType<T>(_t: T.Type) {
@@ -1081,10 +1100,23 @@ func attempt(n: Int) {
}
}
enum Mode: String {
case returnType = "RETURN_TYPE"
case paramType = "PARAMETER_TYPE"
}
@main struct Main {
static func main() {
for i in 1000...1999 {
attempt(n: i)
if CommandLine.arguments.count < 2 {
fatalError("Expected explicit mode in command line arguments, was: \(CommandLine.arguments)")
}
let mode = Mode.init(rawValue: CommandLine.arguments.dropFirst().first!)!
print("Checking in mode: \(mode)...")
for i in 1000...1999 {
attempt(mode, n: i)
}
print("Passed in mode: \(mode)!")
}
}
}