-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPC framework based on tarpc #20
Conversation
@pawelchcki is this PR still relevant, or can we close it? (It looks like #45 is a superset) |
@ivoanjo sorry I missed the notification :|
This PR is actually a superset of #45 😅 |
13f04c5
to
012f383
Compare
Includes the ability to transfer file descriptors between processes, and provides both an async (tokio based) interface as well as synchronous interface
6673374
to
d876750
Compare
"ignored" tests group
dfafc80
to
8e68344
Compare
9e24d80
to
395ca65
Compare
f3cbf47
to
5750f1d
Compare
let mut fds = [0; MAX_FDS]; | ||
|
||
unsafe { | ||
let b = &mut *(buf.unfilled_mut() as *mut [std::mem::MaybeUninit<u8>] as *mut [u8]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unsafe behavior. You're casting uninitialiased memory to a &mut [u8]
. You should call initialize_unfilled instead which will take care of zeroing the memory before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think filling with zero's would be safer, and more secure.
I basically followed what tokio AsyncRead was doing here.
This is part of their optimization - since its a buffer that will be written to - then the contents of memory don't matter as much. But I'd prefer to play on the safe side here
self.send_request(req).await; | ||
self.deadlines.schedule_next_heartbeat(); | ||
self.data.started = true; | ||
if !self.data.started { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
let b = &mut *(buf_window.unfilled_mut() | ||
as *mut [std::mem::MaybeUninit<u8>] | ||
as *mut [u8]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment for the &mut [u8]
6e0579b
to
ecdd9b8
Compare
Thanks @paullegranddc for the review 🙇! 🎉 |
What does this PR do?
Implement a msgpack based RPC / IPC. Where a server is spawned in an async context, and clients can be either async or sync. In addition the RPC can be used in a 1 way style. Where messages are simply sent onto a pipe, without requiring reading of any responses.
This way we can optimize for cases where data transmission is simply in a single direction.
This RPC framework uses
tarpc
crate and adds to it possibility to submit RPC requests without using tokio, and also transport FileDescriptors that can be used to safely delegate processing to the sidecar process.See example use here:
https://github.com/DataDog/libdatadog/pull/20/files#diff-b5cbb946eecfad576b88206a0a05bf1a78331d41fcd5842db73e9b902831a202R26
Some quick benchmarks
Motivation
In some cases the context of data we process needs to live longer than a os process that produces it. For these cases we can spawn a subprocess that will receive the data from producers - and later transform and send to the backend/agent.
For efficient operation we need an optimized RPC, and a method to coordinate sidecar lifecycle.