-
Notifications
You must be signed in to change notification settings - Fork 341
[lldb] Add support for Task names #10684
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
[lldb] Add support for Task names #10684
Conversation
This updates both `OperatingSystemSwiftTasks` and `Task_SummaryProvider` to include a Task's name, if available. See [SE-0469][] for the introduction of task names. The result is that threads representing Swift Tasks will show the given name, and when printing a task, its name will be shown in the summary string. [SE-0469]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0469-task-names.md
@swift-ci test |
lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp
Outdated
Show resolved
Hide resolved
return {}; | ||
} | ||
|
||
TaskStatusRecord getParent(Status &status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For future-proofing you could convert these functions to Expected like so:
llvm::Expected<TaskStatusRecord> getParent() {
addr_t parent = LLDB_INVALID_ADDRESS;
Status status;
if (*this)
parent = process->ReadPointerFromMemory(addr + ParentOffset, status);
if (Status.Fail())
return Status.takeError();
return {process, parent};
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because these functions perform a number of Read*
calls to process, I kept Status
as the means of communicating errors. It makes the code more concise while still having the error handling/control. After the set of Reads (a logical transaction of sorts) have been completed (or failure occurred), the Status
is then converted to Expected
. This pattern I used elsewhere in support of inspection of other concurrency types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave a comment describing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I must admit that this pattern also gave me a hard time convincing me everything was correct. Especially reading something like if (getKind(status) != Kind::TaskName)
, it reads like we're extracting the kind from the status
lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp
Outdated
Show resolved
Hide resolved
|
||
}; // namespace | ||
|
||
llvm::Expected<std::optional<std::string>> GetTaskName(lldb::addr_t task_addr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the optional add anything over just using an empty string for "success, but no name"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My testing shows that I can provide the empty string as a task name, which should be distinguished from no task name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To elaborate, using std::optional<std::string>
allows both a task name of the empty string (which lldb should show), and a task not having a name.
OperatingSystemSwiftTasks::FindTaskName(addr_t task_addr, Process *process) { | ||
auto task_name_or_err = GetTaskName(task_addr, process); | ||
if (auto err = task_name_or_err.takeError()) { | ||
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of returning optional and logging the error, you can return Expected and return llvm::createStringError(...)
. And let the call site do logging or error reporting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or actually, here just return task_name_or_err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah I guess the entire function becomes pointless then :-)
lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.h
Outdated
Show resolved
Hide resolved
|
||
/// Find the (optional) name of the Task at the given address, if any. | ||
std::optional<std::string> FindTaskName(lldb::addr_t task_addr, | ||
Process *process); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't need to me a member, it can be declared and defined inside the cpp file
lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.h
Outdated
Show resolved
Hide resolved
/// Find the Task ID of the task being executed by `thread`, if any. | ||
std::optional<uint64_t> FindTaskId(Thread &thread); | ||
/// Find the address of the Task being executed by `thread`, if any. | ||
std::optional<lldb::addr_t> FindTaskAddress(Thread &thread); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't need to be a member
lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.cpp
Outdated
Show resolved
Hide resolved
if (task_name) | ||
name = llvm::formatv("{0} (Task {1})", *task_name, task_id); | ||
else | ||
name = llvm::formatv("Task {0}", task_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment here: let's strive to always initialize at the declaration. A ternary operator should work fine here, and if this ever becomes more complicated we move it to a helper function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I see a ternary as worse readability. As written above, I consider the initialization to be clearly one of two ways. I'm not aware of any standard conventions or strong arguments that code should be bent to ensure variables are always initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly disagree, but won't insist in the interest of timeliness. But please ponder how would you implement this in a language that does not allow for uninitialized variables? (swift, rust, zig, all the modern ones, and why do they make that choice)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swift does not allow uninitialized variables, but does permit separate declaration and initialization:
var name: String
if whatever {
name = oneName()
} else {
name = anotherName()
}
@swift-ci test |
…hange UpdateThreadList to handle task failures more granularly
@swift-ci test |
@swift-ci test |
@swift-ci test |
@swift-ci test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I think there is still one function that was forgotten in this version, but we can address it afterwards
@swift-ci test |
Thanks, I updated that function. |
@swift-ci test |
@swift-ci test |
@swift-ci test macOS |
@swift-ci test windows |
@swift-ci test macOS |
* [lldb] Add support for Task names This updates both `OperatingSystemSwiftTasks` and `Task_SummaryProvider` to include a Task's name, if available. See [SE-0469][] for the introduction of task names. The result is that threads representing Swift Tasks will show the given name, and when printing a task, its name will be shown in the summary string. [SE-0469]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0469-task-names.md * Add tests * Add docstrings; Switch to process reference; Make functions static; Change UpdateThreadList to handle task failures more granularly * Another switch from pointer to reference; Use GetAddressByteSize * Support 32 bit in TaskStatusRecord * Fix bug in handling of non-Task threads * Change int type of TaskStatusRecord offsets * Make FindTaskId static * Refactor test to (hopefully) work on Linux * Disable test_thread_contains_name on Linux (cherry-picked from commit 262cfab)
* [lldb] Add support for Task names This updates both `OperatingSystemSwiftTasks` and `Task_SummaryProvider` to include a Task's name, if available. See [SE-0469][] for the introduction of task names. The result is that threads representing Swift Tasks will show the given name, and when printing a task, its name will be shown in the summary string. [SE-0469]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0469-task-names.md * Add tests * Add docstrings; Switch to process reference; Make functions static; Change UpdateThreadList to handle task failures more granularly * Another switch from pointer to reference; Use GetAddressByteSize * Support 32 bit in TaskStatusRecord * Fix bug in handling of non-Task threads * Change int type of TaskStatusRecord offsets * Make FindTaskId static * Refactor test to (hopefully) work on Linux * Disable test_thread_contains_name on Linux (cherry-picked from commit 262cfab)
This updates both
OperatingSystemSwiftTasks
andTask_SummaryProvider
to include aTask's name, if available. See SE-0469 for the introduction of task names.
The result is that threads representing Swift Tasks will show the given name, and when
printing a task, its name will be shown in the summary string.
rdar://146940592