Page MenuHomePhabricator

Refactor Unix signals.

Authored by chaoren on Jul 9 2015, 6:45 PM.


  • Consolidate Unix signals selection in UnixSignals.
  • Make Unix signals available from platform.
  • Add jSignalsInfo packet to retrieve Unix signals from remote platform.
  • Get a copy of the platform signal for each remote process.
  • Update SB API for signals.
  • Update signal utility in test suite.

Diff Detail


Event Timeline

chaoren updated this revision to Diff 29417.Jul 9 2015, 6:45 PM
chaoren retitled this revision from to Refactor Unix signals..
chaoren updated this object.
chaoren added reviewers: ovyalov, clayborg.
chaoren added a subscriber: lldb-commits.

Tested on Linux (local and remote). Very likely broken on other platform (will test later).

Some thoughts:

  1. Is it worth the effort to make Platform::GetUnixSignals const? Same thing with most (all?) of the Get* methods in PlatformRemoteGDBServer. I don't know if we should bother with const-correctness of remote protocols.
  2. *Signals.{h,cpp} should probably be moved out of Process/Utility. But where?
  3. Are Should{Suppress,Stop,Notify} per process properties or general properties of the signals. If it's per process, each process will need its own copy (which we didn't have before).
chaoren updated this revision to Diff 29418.Jul 9 2015, 7:05 PM
  • UnixSignals::Reset should be virtual.
labath added a subscriber: labath.Jul 10 2015, 1:34 AM
68 ↗(On Diff #29418)

You are changing the public API here. We are maintaining binary compatibility wrt. SBAPI. You can see for details, but the short version is that you can add signatures, but not modfy or remove existing ones.

78 ↗(On Diff #29418)

Modifying the members ( = size of the object) is also a no-no.

1833 ↗(On Diff #29418)

Please rename to signals_sp, per coding conventions.

1078 ↗(On Diff #29418)

I am not sure this function belongs to the Host layer anymore (which I understand as providing information about the host lldb is running on), since it now provides signals for any platform. Perhaps if we move this function to process/Utility then we wouldn't have the host layer calling back into other stuff (was this the reason for your question #2?). What do you think?

chaoren added inline comments.Jul 10 2015, 9:13 AM
68 ↗(On Diff #29418)

This is protected: so it's not part of the public API. Actually, now that you mention it, it should probably be private: instead, since there's no inheritance.

78 ↗(On Diff #29418)

We can probably do without the process pointer (depending on the answer to my 3rd question). But I'm not sure it makes sense to use a WP for UnixSignals.

1078 ↗(On Diff #29418)

We can probably move this function to UnixSignals itself. The signals are usually platform specific rather than process specific, so I thought it was a little weird to still have them in Process/Utility.

clayborg requested changes to this revision.Jul 10 2015, 9:45 AM
clayborg edited edge metadata.

So what is the overall goal of this patch? I am assuming the jist of this patch is to just get the JSON packet to get unix signals from the remote GDB server.

The following things MUST be true:

  • Each process must have its own unix signals, i.e. they must be separate UnixSignals instances. Different processes might setup which signals to ignore and pass along and notify differently and this shouldn't change.
  • You can't add ivars to lldb::SB classes there must be one shared_ptr, unique_ptr or raw pointer and its size must match what was there before for API compatability

I would rather not see SBPlatform get UnixSignals if we can help it. It would be nice from the standpoint that you might be able to grab a copy of them and modify them before any processes are launched, but I don't see us doing any of this anywhere so I would rather avoid it until we do. The theory is you can modify a platforms unix signals, and then each process will get a copy of the current platforms signals when the process is created, but each process needs to have its own instance of UnixSignals so each process can set which signals to stop/notify/continue from separately, all processes can't use the same instance otherwise you make other processes stop when they didn't want to for specified signals. We have lldb.util.get_signal_number() that is trying to take advantage of the platform having unix signals but I would argue that we should have a lldb.SBProcess available anytime we need this information, so the platform doesn't really need signals right now. So I believe Process should still have a m_unix_signals object that is owned by it just like it used to and it can be seeded with startup values if needed.

So what I don't like about the platform having unix signals and this patch:

  • Each platform might be able to guess what signals it has by making a constant copy of some signals from some version of the their previous OS's but this can get out of date
  • Each platform could provide the correct signals if it is connected to a remote platform, but connection to a platform isn't required (for iOS we don't connect to a remote platform) and the lldb-server on the other side might not support the JSON signal packet, and if not then we are back to guessing as in the above step
  • We can't share unix signals between multiple processes, they each need to have their own instance

What I do like about the platform having unix signals:

  • We can get ahold of SBUnixSignals before we run and set up signals so each process that gets launched can init itself with a copy of one set of settings (but this patch doesn't do that).

A quick not about public API stuff:

  • Any changes in the public API must be additions only and no changes to previous API can be made
  • no ivar size changes
  • Don't bother with any "const" specifications on ANY methods as they are useless. The only thing it does it makes sure the shared_ptr, unique_ptr or pointer can't be changed. We have some functions that people put "const" on erroneously, but we are stuck with it now since we can't change public API. We shouldn't add more.

So let me know what you think after reading my above comments. I would almost rather this patch just do the following:

  • introduce the new JSON unix signal packet and use it for ProcessGDBRemote
  • Don't do any of the SBPlatform stuff, the only thing we are using it for is lldbutil.get_signal_number() and we should be able to use the current process for this
  • Backout all public API changes
  • Backout all host changes
77–78 ↗(On Diff #29418)

All objects in the public API must never change size so you can't add one here. If clients update LLDB they should still be able to link against the LLDB public interface without anything changing, adding an ivar changes the byte size, anyone that might have inherited from or use a SBUnixSignal as an ivar, will now crash.

248–249 ↗(On Diff #29418)

I am confused as to why this change was made. In the host layer there should only be 1 host set of unix signals. If you are trying to make a grab bag for any kind of canned unix signals, please make a static function in the lldb_private::UnixSignals class.

This revision now requires changes to proceed.Jul 10 2015, 9:45 AM

It would be nice from the standpoint that you might be able to grab a copy of them and modify them before any processes are launched, but I don't see us doing any of this anywhere so I would rather avoid it until we do.

We do this in the gdb remote tests. I added the kill -l workaround, but that doesn't work on prehistoric shells.

Each platform might be able to guess what signals it has by making a constant copy of some signals from some version of the their previous OS's but this can get out of date

Yes, that's the fall back. Doesn't Process do this currently? If so, I don't see how this is worse.

chaoren edited edge metadata.

Address reviews.

  • Moved signal selection out of Host and into UnixSignals itself.
  • Single UnixSignalsWP in SBUnixSignals for API compatibility.
  • Each process gets its own instance of UnixSignals.
  • ProcessGDBRemote gets a copy from PlatformRemoteGDBServer.
chaoren updated this object.Jul 10 2015, 1:50 PM
chaoren edited edge metadata.
chaoren marked 6 inline comments as done.Jul 10 2015, 1:58 PM

Note, there is a document that describes the rules for coding the SB API's:

if there's something there that isn't clear, feel free to clarify the text there...


ovyalov added inline comments.Jul 13 2015, 10:15 AM
111 ↗(On Diff #29488)

Please add check for not-null signals_sp

144 ↗(On Diff #29488)


978 ↗(On Diff #29488)

Should it be Host::GetUnixSignals?

263 ↗(On Diff #29488)

Could you store result of Host::GetUnixSignals() as local variable?

343 ↗(On Diff #29488)

Please add a check that index < m_signals.size()

chaoren added inline comments.Jul 13 2015, 10:28 AM
978 ↗(On Diff #29488)

I think it's better to use the default Unix signal set without any assumptions about the remote platform, than to assume that the remote platform would be the same as the host.

chaoren added inline comments.Jul 13 2015, 10:32 AM
111 ↗(On Diff #29488)

Do we not want to log if it's null?

I think SBUnixSignals(<null>)::SetShouldSuppress is still good to see.

clayborg requested changes to this revision.Jul 13 2015, 10:54 AM
clayborg edited edge metadata.

Looks fine, just some possible cleanup with respect to calling "get_signal_number(signal_name, process):" as mentioned in inlined comments.

935–939 ↗(On Diff #29488)

We should be getting this info from the current process if we can. This seems like it can introduce test suite errors if our const cached notion of what signals are that are retrieved from the static UnixSignals function doesn't actually match the real current process that might have fetched the info from the remote GDB server. Can you check on all of the callsites that use this get_signal_number() function and see if any have a live process they can supply?

I would like to see this function changed to:

def get_signal_number(signal_name, process):
    signals = None
    if process:
       signals = process.GetUnixSignals()
        platform = lldb.remote_platform
        if platform and platform.IsValid():
            signals = platform.GetUnixSignals()
    if signals and signals.IsValid():
This revision now requires changes to proceed.Jul 13 2015, 10:54 AM
chaoren added inline comments.Jul 13 2015, 11:06 AM
935–939 ↗(On Diff #29488)

I don't think it's possible for the signals to be different between the platform and a process, since I followed your advice and each process gets a copy of the signals that the platform fetched remotely.

So what happens if we are not connected to a remote platform? Do we get UnixSignal that are empty? Do we fall back to some constant notion of what we think the signal should be?

We use local signals.

return getattr(signal, signal_name)

I was under the assumption that, in general, you need a remote platform to
have a remote process. Is the iOS thing not a special case? Even in that
specific case, the local host signals should suffice (since that's what we
had before I added the get_signal_number utility).

chaoren edited edge metadata.
  • Properly defer RemoteUnixSignals through the platform chain.
  • Also address ovyalov's reviews.
clayborg accepted this revision.Jul 13 2015, 12:59 PM
clayborg edited edge metadata.

That is fine, lets start with this and we can iterate on it if when we need to do so.

This revision is now accepted and ready to land.Jul 13 2015, 12:59 PM
ovyalov accepted this revision.Jul 13 2015, 1:41 PM
ovyalov edited edge metadata.


chaoren updated this object.Jul 13 2015, 2:06 PM
chaoren edited edge metadata.
chaoren updated this object.Jul 13 2015, 2:08 PM

Minor fixups and rebase.

  • Update xcode project file.
  • Remove unused include.
This revision was automatically updated to reflect the committed changes.