This is an archive of the discontinued LLVM Phabricator instance.

[lldb/Plugin] Sort the ScriptedProcess' thread list before creating threads
ClosedPublic

Authored by mib on Mar 24 2022, 12:49 PM.

Details

Summary

With Scripted Processes, in order to create scripted threads, the blueprint
provides a dictionary that have each thread index as the key with the respective
thread instance as the pair value.

In Python, this is fine because a dictionary key can be of any type including
integer types:

>>> {1: "one", 2: "two", 10: "ten"}
{1: 'one', 2: 'two', 10: 'ten'}

However, when the python dictionary gets bridged to C++ with convert it to a
StructuredData::Dictionary that uses a std::map<ConstString, ObjectSP>
for storage.

Because std::map is an ordered container and ours uses the ConstString
type for keys, the thread indices gets converted to strings which makes the
dictionary sorted alphabetically, instead of numerically.

If the ScriptedProcesse has 10 threads or more, it causes thread “10”
(and higher) to be after thread “1”, but before thread “2”.

In order to solve this, this sorts the thread info dictionary keys
numerically, before iterating over them to create ScriptedThreads.

rdar://90327854

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>

Diff Detail

Event Timeline

mib created this revision.Mar 24 2022, 12:49 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 12:49 PM
mib requested review of this revision.Mar 24 2022, 12:49 PM
JDevlieghere added inline comments.Mar 24 2022, 10:24 PM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
352

Won't this overflow when you return the example from the summary?

{1: "one", 2: "two", 10: "ten"}

Would it be easier to populate our own map<size_t, ObjectSP> and iterate over that below?

mib added inline comments.Mar 25 2022, 9:16 AM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
352

I don't see why it would overflow 🧐

JDevlieghere added inline comments.Mar 25 2022, 9:38 AM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
352

You create a vector with 3 elements:

std::vector<llvm::StringRef> sorted_keys(keys->GetSize());

But you use the key from the dictionary to index the vector:

sorted_keys[0] = "";
sorted_keys[1] = "one";
sorted_keys[2] = "two";
-- end of vector --
sorted_keys[10] = "ten";
mib added inline comments.Mar 25 2022, 11:06 AM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
352

You're right! I didn't hit this because in the Scripted Process case, indices are 0 based, so that works perfectly but I guess I could use a map to prevent a potential overflow

mib updated this revision to Diff 418325.EditedMar 25 2022, 2:25 PM
mib marked 2 inline comments as done.

Implement @JDevlieghere suggestions:

  • Use a std::map<size_t, ObjectSP> to sort the thread info dictionary to prevent potential overflows
JDevlieghere added inline comments.Mar 25 2022, 2:36 PM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
321–342

Instead of this callback, can we simplify the code by iterating over the keys and populate the map that way?

mib added inline comments.Mar 25 2022, 2:54 PM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
321–342

We don't have iterators to iterate over StructuredData containers with a range-based loop, so we can only iterate over them using indices ...

I find it ungracious to do it that way because we have to call GetItemAtIndex(idx) to get the StructuredData::Object element from the array, that's why I used the ForEach method instead.

I think we can improve StructuredData containers to be more customizable and operate better with the std/adl utilities, it should be done separately.

mib added inline comments.Mar 25 2022, 2:57 PM
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
321–342

I think we've discussed this offline, but if we made the StructuredData::Array templated (with a default template parameter), we could prevent having to sort ourself the thread dictionary, and loop twice over it (which annoys me quite a bit 😅😅)

JDevlieghere accepted this revision.Mar 25 2022, 2:57 PM

LGMT

lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
321–342

Okay, that's unfortunate. Thanks for the explanation!

This revision is now accepted and ready to land.Mar 25 2022, 2:57 PM