Problem:
- Many constructors are defined as `{}` rather than using the ` =
default` compiler-provided constructor.
- Some types provide an implicit conversion operator from `nullptr_t`
instead of requiring the caller to default construct. This violates
the C++ Core Guidelines suggestion to declare single-argument
constructors explicit
(https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c46-by-default-declare-single-argument-constructors-explicit).
Solution:
- Change default constructors to use the compiler-provided default
constructor.
- Remove implicit conversion operators from `nullptr_t` and change
usage to enforce type consistency without conversion.
Problem:
- `(void)` simply casts the expression to void. This is understood to
indicate that it is ignored, but this is really a compiler trick to
get the compiler to not generate a warning.
Solution:
- Use the `[[maybe_unused]]` attribute to indicate the value is unused.
Note:
- Functions taking a `(void)` argument list have also been changed to
`()` because this is not needed and shows up in the same grep
command.
It is now possible to use the special IPC::File type in message arguments. In
C++, the type is nothing more than a wrapper over a file descriptor. But when
serializing/deserializing IPC::File arguments, LibIPC will use the sendfd/recvfd
kernel APIs instead of sending the integer inline.
This makes it quite convenient to pass files over IPC, and will allow us to
significantly tighten sandboxes in the future :^)
Closes https://github.com/SerenityOS/serenity/issues/3643
Since we're using byte streamed Unix sockets for the IPC protocols,
it's possible for the kernel to run out of socket buffer space with
a partial message near the end of the buffer.
Handle this situation in IPC::Connection by buffering the bytes of
what may be a partial message, and prepending them to the incoming
data next time we receive from the peer.
This fixes WindowServer asserting when a peer is spamming it hard.
This would previously fail at runtime, and it would have zero indication
of what exactly went wrong.
Also adds `AK::DependentFalse<Ts...>', which is a...dependent false.
Writing to the socket may trigger a close of the socket descriptor
if a disconnect was detected. We need to check if it is still valid
when waiting for a response after attempting to send a synchronous
message.
Fixes#3515
Because we're closing a file descriptor, we need to disable any
Notifier that is using it so that the EventLoop does not use invalid
file descriptors.
Fixes#3508
This was previously used to defer handling disconnections until the
next event loop iteration. We now achieve the same with simple use
of deferred_invoke(). :^)
This patch introduces IPC::Connection which becomes the new base class
of ClientConnection and ServerConnection. Most of the functionality
has been hoisted up to the base class since almost all of it is useful
on both sides.
This gives us the ability to send synchronous messages in both
directions, which is needed for the WebContent server process.
Unlike other servers, WebContent does not mind blocking on a response
from its client.
When waiting for a specific message, only consider messages
from the peer endpoint. Otherwise a message with the same id
for the local endpoint may be misinterpreted.
This fixes the Terminal sometimes hanging after bootup because
a local endpoint message is mistaken for the CreateMenuResponse
message.
This stops servers from crashing when a client's socket buffer becomes
full and we can't post any more messages to it. Normally this means the
client process is hanged/spinning, but I suppose this could also happen
under severe system load.
It's unclear to me what a better solution here would be. We can't keep
buffering messages indefinitely if the client is just never going to
receive them anyway. At some point we have to cut our losses, and it
seems pretty reasonable to let the kernel socket buffer be the cutoff.
It will be the responsibility of the individual server implementations
to avoid sending messages to clients that may be unable to handle them.
Instead of always running the responsiveness timer for IPC clients,
we now only start it after sending a message. This avoids waking up
otherwise idle clients to do ping/pong busywork.
IPC::ClientConnection now tracks the time since the last time we got
a message from the client and calls a virtual function on itself after
3 seconds: may_have_become_unresponsive().
Subclasses of ClientConnection can then react to this if they like.
We use this mechanism in WindowServer to send out a friendly Ping
message to the client. If he doesn't Pong within 1 second, we mark
the client as "unresponsive" and recompose all of his windows with
a darkened appearance and amended title until he Pongs us.
This is a little on the aggressive side and we should figure out a way
to wake up less often. Perhaps this could only be done to windows the
user is currently interacting with, for example.
Anyways, this is pretty cool! :^)
Now most classes dictate how they are serialized and deserialized when
transmitted across LibIPC sockets. This also makes the IPC compiler
a bit simpler. :^)
Same issue here as we had with RefPtr and NonnullRefPtr.
Since we can't make copies of an owning pointer, we don't get quite the
same static_ptr_cast<T> here. Instead I've only added a new templated
version of OwnPtr::release_nonnull() in this patch, to solve the only
issue that popped up.
I'm not sure what the best solution here is, but this works for now.
Instead of passing the BufferStream, pass the Decoder. I'd like to stop
using BufferStream eventually anyway, so it's good to get it out of any
API's where it's in currently.
This shaves ~5 seconds off of a full build, not too bad. Also it just
seems nicer to push this logic out to classes. It could be better but
it's a start. :^)
Compiling anything that includes generated IPC messages is painfully
slow at the moment. This moves the encoding helpers out of line, which
helps a bit. Doing the same for decoding will help more.