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
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits