Skip to content
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

tracing-journald: Send large journal payloads through memfd #1744

Merged
merged 1 commit into from Nov 30, 2021
Merged

tracing-journald: Send large journal payloads through memfd #1744

merged 1 commit into from Nov 30, 2021

Conversation

swsnr
Copy link
Contributor

@swsnr swsnr commented Nov 23, 2021

See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and while it's well documented in cmsg(3) I had to fiddle a bit because the corresponding functions in libc aren't const and thus don't permit a direct allocation of the buffer as most cmsg C code around does.

Closes #1698

Motivation

Linux limits the maximum amount of data permitted for a single Unix datagram; sending large payloads directly will fail.

Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for EMSGSIZE from send(); in this case write the payload to a memfd, seal it, and pass it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on nix, and instead implements fd forwarding directly with some bits of unsafe libc code.

@swsnr swsnr requested review from davidbarsky, hawkw and a team as code owners November 23, 2021 19:57
@swsnr
Copy link
Contributor Author

swsnr commented Nov 23, 2021

/cc @Ralith

tracing-journald/src/memfd.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/memfd.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/memfd.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
@swsnr
Copy link
Contributor Author

swsnr commented Nov 26, 2021

@Ralith @hawkw Thanks for your help with the buffer size issue 🙏 Tests pass now, and I'd appreciate a new review 😊

Copy link
Collaborator

@Ralith Ralith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@swsnr swsnr requested a review from hawkw November 29, 2021 20:04
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks good to me! i commented on some minor style nits, but i'm happy to merge this PR as-is.

tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/lib.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
tracing-journald/src/socket.rs Outdated Show resolved Hide resolved
@swsnr swsnr requested review from Ralith and hawkw November 30, 2021 10:24
Linux limits the maximum amount of data permitted for a single Unix
datagram; if our payload exceeds this platform-dependent size we write
the content to a memfd and pass this memfd to journald, per
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/.

Add a test which checks a large message.

Closes #1698
@hawkw hawkw merged commit 63d4170 into tokio-rs:master Nov 30, 2021
@swsnr
Copy link
Contributor Author

swsnr commented Nov 30, 2021

@hawkw @Ralith Thanks for your review and for merging this 🙏

@swsnr swsnr deleted the 1698-message-size branch November 30, 2021 18:57
@Ralith
Copy link
Collaborator

Ralith commented Nov 30, 2021

Thanks for the contribution!

hawkw pushed a commit that referenced this pull request Dec 2, 2021
See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and
while it's well documented in `cmsg(3)` I had to fiddle a bit because
the corresponding functions in libc aren't const and thus don't permit a
direct allocation of the buffer as most `cmsg` C code around does.

Closes #1698

## Motivation

Linux limits the maximum amount of data permitted for a single Unix
datagram; sending large payloads directly will fail.

## Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for `EMSGSIZE` from
`send()`; in this case write the payload to a memfd, seal it, and pass
it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on `nix`, and instead
implements fd forwarding directly with some bits of unsafe `libc` code.
@hawkw hawkw mentioned this pull request Dec 2, 2021
hawkw pushed a commit that referenced this pull request Dec 3, 2021
See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and
while it's well documented in `cmsg(3)` I had to fiddle a bit because
the corresponding functions in libc aren't const and thus don't permit a
direct allocation of the buffer as most `cmsg` C code around does.

Closes #1698

## Motivation

Linux limits the maximum amount of data permitted for a single Unix
datagram; sending large payloads directly will fail.

## Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for `EMSGSIZE` from
`send()`; in this case write the payload to a memfd, seal it, and pass
it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on `nix`, and instead
implements fd forwarding directly with some bits of unsafe `libc` code.
hawkw pushed a commit that referenced this pull request Dec 19, 2021
See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and
while it's well documented in `cmsg(3)` I had to fiddle a bit because
the corresponding functions in libc aren't const and thus don't permit a
direct allocation of the buffer as most `cmsg` C code around does.

Closes #1698

## Motivation

Linux limits the maximum amount of data permitted for a single Unix
datagram; sending large payloads directly will fail.

## Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for `EMSGSIZE` from
`send()`; in this case write the payload to a memfd, seal it, and pass
it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on `nix`, and instead
implements fd forwarding directly with some bits of unsafe `libc` code.
hawkw pushed a commit that referenced this pull request Dec 19, 2021
See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and
while it's well documented in `cmsg(3)` I had to fiddle a bit because
the corresponding functions in libc aren't const and thus don't permit a
direct allocation of the buffer as most `cmsg` C code around does.

Closes #1698

## Motivation

Linux limits the maximum amount of data permitted for a single Unix
datagram; sending large payloads directly will fail.

## Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for `EMSGSIZE` from
`send()`; in this case write the payload to a memfd, seal it, and pass
it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on `nix`, and instead
implements fd forwarding directly with some bits of unsafe `libc` code.
hawkw pushed a commit that referenced this pull request Dec 20, 2021
See #1698: Properly write large payloads to journal.

I'd appreciate a very careful review; this cmsg stuff is nasty, and
while it's well documented in `cmsg(3)` I had to fiddle a bit because
the corresponding functions in libc aren't const and thus don't permit a
direct allocation of the buffer as most `cmsg` C code around does.

Closes #1698

## Motivation

Linux limits the maximum amount of data permitted for a single Unix
datagram; sending large payloads directly will fail.

## Solution

Follow systemd.io/JOURNAL_NATIVE_PROTOCOL/ and check for `EMSGSIZE` from
`send()`; in this case write the payload to a memfd, seal it, and pass
it on to journald via a corresponding SCM_RIGHTS control message.

Per discussion in #1698 this adds no dependency on `nix`, and instead
implements fd forwarding directly with some bits of unsafe `libc` code.
hawkw added a commit that referenced this pull request Dec 30, 2021
# 0.2.1 (December 29, 2021)

This release improves how `tracing-journald` communicates with `journald`,
including the handling of large payloads.

### Added

- Use an unconnected socket, so that logging can resume after a `journald`
  restart ([#1758])

### Fixed

- Fixed string values being written using `fmt::Debug` ([#1714])
- Fixed `EMSGSIZE` when log entries exceed a certain size ([#1744])

A huge thank-you to new contributor @lunaryorn, for contributing all of the
changes in this release!

[#1714]: #1714
[#1744]: #1744
[#1758]: #1758
hawkw added a commit that referenced this pull request Dec 30, 2021
# 0.2.1 (December 29, 2021)

This release improves how `tracing-journald` communicates with `journald`,
including the handling of large payloads.

### Added

- Use an unconnected socket, so that logging can resume after a `journald`
  restart ([#1758])

### Fixed

- Fixed string values being written using `fmt::Debug` ([#1714])
- Fixed `EMSGSIZE` when log entries exceed a certain size ([#1744])

A huge thank-you to new contributor @lunaryorn, for contributing all of the
changes in this release!

[#1714]: #1714
[#1744]: #1744
[#1758]: #1758
#[cfg(not(unix))]
fn send_payload(&self, _opayload: &[u8]) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSRV is currently set to 1.49 but io::ErrorKind::Unsupported was stabilized in 1.53.

This wasn't caught on CI because it's gated behind #[cfg(not(unix))] 🙃

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ughhh, that's annoying. currently we don't build MSRV on windows (or macOS) to avoid having a really huge number of CI builds... but maybe we should be.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really much of an issue? Does anyone actually use tracing-journald on Windows? I only added this because tracing-journald gets built on Windows on the pipeline; it's only there to silence Github actions, I never assumed anyone would actually build this on Windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words as far as I'm concerned we could also just use unimplemented!() here and have it panic.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing it with NotFound would be fine. We shouldn't panic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by the way, did anyone actually hit this MSRV violation in their build?

I "hit" it, but only inasmuch as I was doing a minver check on the repository from windows.

For #2231 I just replaced this with ErrorKind::Other.

MSRV tests on other OSes

I think in general it's fine to assume the Linux build will catch things, as the OS-gated functionality is rare enough, and we can fix violations when they come up.

If we do want to check other targets, it should be via cross-compile where possible since linux hosted runner time is cheaper, and just a check is sufficient.

(Ultimately CI-wise this comes back to the downside of a monorepo being testing the entire monorepo to verify a subpackage-local change... though this is sometimes desirable since e.g. tracing-core gets a significant amount of test coverage only from testing of tracing or even tracing-subscriber...)

don't compile on windows

There are AIUI four reasonable choices (of which only the latter pair are legally semver compatible):

  • #![cfg] the entire crate to only expose any API on platforms where it makes sense. This is IIRC the approach taken by winapi. Consumers #[cfg] their usage.
  • compile_error! on platforms where the crate doesn't make any sense. Consumers need to use a target-dependent dependency as well as #[cfg] their usage.
  • panic! (or error) entrypoints into the API on unsupported platforms. Consumers #[cfg] their usage (or tolerate an error on supported platforms as well).
  • Stub functionality on unsupported platforms. IIUC tracing-journald is purely a sink, so stubbing it as > /dev/null ($nullpwsh) isn't wrong, just perhaps unexpected. Consumers can unconditionally use the API and just implicitly degrade on unsupported platforms.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make another merge request which uses Other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, @CAD97 already opened one, thanks a lot 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hawkw I doubt that anyone's building and using tracing-journald on Windows; that wouldn't make any sense.

But I'm fine with using ErrorKind::Other.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think NotFound would be wrong, semantically; after all, we're not searching for anything here

Semantically, we are searching for JOURNALD_PATH. This is the error that will be returned when running on a Unix without journald, and unconditionally when running on Windows.

@swsnr
Copy link
Contributor Author

swsnr commented Jul 20, 2022 via email

@Ralith
Copy link
Collaborator

Ralith commented Jul 20, 2022

Probably not worth the trouble since it's dead, yeah. If someone's feeling motivated to make this code extra pretty, we'd probably be better off just reducing the amount of dead code that gets compiled outright.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

tracing-journald ignores EMSGSIZE from send()
4 participants