[Lldb-commits] [lldb] [lldb] Updated lldb-server to spawn the child process and share socket (PR #101283)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 6 05:31:22 PDT 2024


labath wrote:

I would start looking at this from the other end. Let's identify logical pieces of functionality that can be shared between the various modes of operation (fork/exec/singleserver), and try to refactor to code to fit that. While doing that, I think an important criteria should be whether some of the code is platform-specific. If it is, the function containing that should be as small as possible so that the ifdef doesn't occur in a deeply nested code (deeply nested ifdefs are much harder to reason about than one that occurs at the top level.

The first obvious piece of functionality I see is the one which serves a single connection. This is something we need to execute in all three code paths. It should definitely be a function of its own (I'm going to call it `ServeSingleConnection` here, but there may be a name that better fits local conventions), so that we can just call it, instead of reaching it through a web of compile and runtime conditionals.

The second one is the piece that serves multiple connections (let's call it `ServeManyConnections`) and handles handing them off to subprocesses. This one is tricky because it going to be platform specific. I'm not clear on whether it should be a single function with embedded ifdefs or two implementations of a single function, but I think it should be as small as possible so that the platform specificities really stand out.

I would try to implement it as something like this (where the two functions in the while loop are platform-specific code):
```
void ServeManyConnections(...) {
  while (conn = AcceptNewConnection()) {
    ServeInSubprocess(conn);
    ReapSubprocessesIfNeeded();
  }
}
```

... but I can also image other schemes. (BTW, I don't think you can get rid of the waitpid calls completely, as you need to reap the zombies even if you're not going to do anything with them).

Then I think we can structure the main (or something main-like) function as something like:
```
int main() {
  ...

  if (getting_connection_from_parent)
    return AcceptConnectionFromParent(...); // retrieves the connection and calls ServeSingleConnection

  if (!server_mode) // no --server flag
    return ServeSingleConnection(...)

  return ServeManyConnections(...);
}
```

I know this is handwavy, but that's sort of the goal I think we should aim for. It will get messier once all of the arguments (which I've conveniently ignored here) get added, but feel free to add structs or classes to group things as they make sense. Once we have this, I think it will also be clearer which code (if any) we want to put in some common libraries. Doing everything at once also may not be the best idea -- I can totally see how a preparatory patch which just refactors things without adding windows support would make sense here.

(Also @DavidSpickett, feel free to chime in, I shouldn't be the only one dictating conditions here.:)

https://github.com/llvm/llvm-project/pull/101283


More information about the lldb-commits mailing list