[GH-ISSUE #1065] ironbar var set: accept bigger values #7361

Closed
opened 2026-05-23 02:54:04 +01:00 by JakeStanger · 9 comments
Owner

Originally created by @postsolar on GitHub (Jun 24, 2025).
Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1065

Is your feature request related to a problem? Please describe.

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

  1. Use this config:
{
  "start": [
    {
      "type": "label",
      "label": "#foo"
    }
  ]
}
  1. Run ironbar var set foo "$(printf '%965s' a)", see ok
  2. Run ironbar var set foo "$(printf '%966s' a)", see
2025-06-24T01:52:17.432655Z ERROR ironbar: 107: Connection reset by peer (os error 104)

I understand this to mean I can't pass an argument this long for setting an Ironvar. I'm not well-versed in lower-level Linux details, from some googling it seems like it should be fine but for some reason it stops working after the 966th byte. I don't know if it's actually related to argument size, so don't mind the feature request labeling too much.

967 bytes isn't that much, I want a label (within a popup) with more than that.

Describe the solution you'd like

A clear and concise description of what you want to happen.
The more info here about what you are trying to achieve, the better - there's likely more than one way to go about implementing a solution.

If it is in fact related to argument size, then it would be nice to have any of:

  • command-with-long-output | ironbar var set foo
  • command-with-long-output | ironbar var set foo -
  • command-with-long-output | ironbar var set foo --from=/dev/stdin

Describe alternatives you've considered

A clear and concise description of any alternative solutions or features you've considered.

Using {{ script }} (necessarily in poll mode, as watch would only show the last line), but I'd prefer a different architecture for my use case.

I have a long-running service that does a lot of things related to Hyprland, among them setting some Ironvars. It's simple and centralized to this service, feels nicer and easier to manage this way.

Additional context

Add any other context or screenshots about the feature request here.

Originally created by @postsolar on GitHub (Jun 24, 2025). Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1065 **Is your feature request related to a problem? Please describe.** > A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 1. Use this config: ```json { "start": [ { "type": "label", "label": "#foo" } ] } ``` 2. Run `ironbar var set foo "$(printf '%965s' a)"`, see `ok` 3. Run `ironbar var set foo "$(printf '%966s' a)"`, see ``` 2025-06-24T01:52:17.432655Z ERROR ironbar: 107: Connection reset by peer (os error 104) ``` I understand this to mean I can't pass an argument this long for setting an Ironvar. I'm not well-versed in lower-level Linux details, from some googling it seems like it should be fine but for some reason it stops working after the 966th byte. I don't know if it's actually related to argument size, so don't mind the feature request labeling too much. 967 bytes isn't that much, I want a label (within a popup) with more than that. **Describe the solution you'd like** > A clear and concise description of what you want to happen. > The more info here about what you are trying to achieve, the better - there's likely more than one way to go about implementing a solution. If it is in fact related to argument size, then it would be nice to have any of: - `command-with-long-output | ironbar var set foo` - `command-with-long-output | ironbar var set foo -` - `command-with-long-output | ironbar var set foo --from=/dev/stdin` **Describe alternatives you've considered** > A clear and concise description of any alternative solutions or features you've considered. Using `{{ script }}` (necessarily in `poll` mode, as `watch` would only show the last line), but I'd prefer a different architecture for my use case. I have a long-running service that does a lot of things related to Hyprland, among them setting some Ironvars. It's simple and centralized to this service, feels nicer and easier to manage this way. **Additional context** > Add any other context or screenshots about the feature request here.
JakeStanger 2026-05-23 02:54:04 +01:00
Author
Owner

@postsolar commented on GitHub (Jun 24, 2025):

In case issue description is too messy, here's a sum-up:

  1. I have a label widget with an ironvar
  2. I eventually run ironbar var set that-var some-long-text
  3. It fails due to text being too long. It's fine with shorter pieces of text or when the var is set within a script or when the label has a static value. It only fails when it's a var set via the IPC and value is long.
<!-- gh-comment-id:2998624308 --> @postsolar commented on GitHub (Jun 24, 2025): In case issue description is too messy, here's a sum-up: 1. I have a `label` widget with an ironvar 2. I eventually run `ironbar var set that-var some-long-text` 3. It fails due to text being too long. It's fine with shorter pieces of text or when the var is set within a `script` or when the label has a static value. It only fails when it's a var set via the IPC and value is long.
Author
Owner

@JakeStanger commented on GitHub (Jun 24, 2025):

I suspect this is a nice and simple fix. The IPC buffers have a capacity of 1024 bytes, which I guess doesn't grow as its passed as a slice.

github.com/JakeStanger/ironbar@d45eb2a69a/src/ipc/server/mod.rs (L85-L86)

github.com/JakeStanger/ironbar@d45eb2a69a/src/ipc/client.rs (L27-L28)

I think using read_to_end is probably a better fit here:
https://docs.rs/tokio/latest/tokio/io/trait.AsyncReadExt.html#method.read_to_end

<!-- gh-comment-id:2999302241 --> @JakeStanger commented on GitHub (Jun 24, 2025): I suspect this is a nice and simple fix. The IPC buffers have a capacity of 1024 bytes, which I guess doesn't grow as its passed as a slice. https://github.com/JakeStanger/ironbar/blob/d45eb2a69a44eb870b54393429af50776801a9f3/src/ipc/server/mod.rs#L85-L86 https://github.com/JakeStanger/ironbar/blob/d45eb2a69a44eb870b54393429af50776801a9f3/src/ipc/client.rs#L27-L28 I think using `read_to_end` is probably a better fit here: https://docs.rs/tokio/latest/tokio/io/trait.AsyncReadExt.html#method.read_to_end
Author
Owner

@JakeStanger commented on GitHub (Jun 24, 2025):

Regarding your initial request, this can be achieved directly through a clap library:
https://docs.rs/clap-stdin/latest/clap_stdin/

Alternatively it should be easy enough to look for a - value and lock stdin manually without it...

<!-- gh-comment-id:2999305444 --> @JakeStanger commented on GitHub (Jun 24, 2025): Regarding your initial request, this can be achieved directly through a clap library: https://docs.rs/clap-stdin/latest/clap_stdin/ Alternatively it should be easy enough to look for a `-` value and lock stdin manually without it...
Author
Owner

@postsolar commented on GitHub (Jun 24, 2025):

I tried using read_to_end and it works but I don't know how to add EOF signal to close the stream, so CLI hangs until Ctrl-C.

diff --git a/src/ipc/client.rs b/src/ipc/client.rs
index 820ace5..ce4f2da 100644
--- a/src/ipc/client.rs
+++ b/src/ipc/client.rs
@@ -24,8 +24,8 @@ impl Ipc {

         stream.write_all(&write_buffer).await?;

-        let mut read_buffer = vec![0; 1024];
-        let bytes = stream.read(&mut read_buffer).await?;
+        let mut read_buffer = Vec::new();
+        let bytes = stream.read_to_end(&mut read_buffer).await?;

         let response = serde_json::from_slice(&read_buffer[..bytes])?;
         Ok(response)
diff --git a/src/ipc/server/mod.rs b/src/ipc/server/mod.rs
index 0f944b7..5f210d2 100644
--- a/src/ipc/server/mod.rs
+++ b/src/ipc/server/mod.rs
@@ -82,8 +82,8 @@ impl Ipc {
     ) -> Result<()> {
         let (mut stream_read, mut stream_write) = stream.split();

-        let mut read_buffer = vec![0; 1024];
-        let bytes = stream_read.read(&mut read_buffer).await?;
+        let mut read_buffer = Vec::new();
+        let bytes = stream_read.read_to_end(&mut read_buffer).await?;

         // FIXME: Error on invalid command
         let command = serde_json::from_slice::<Command>(&read_buffer[..bytes])?;
<!-- gh-comment-id:3000063205 --> @postsolar commented on GitHub (Jun 24, 2025): I tried using `read_to_end` and it works but I don't know how to add EOF signal to close the stream, so CLI hangs until Ctrl-C. ```diff diff --git a/src/ipc/client.rs b/src/ipc/client.rs index 820ace5..ce4f2da 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -24,8 +24,8 @@ impl Ipc { stream.write_all(&write_buffer).await?; - let mut read_buffer = vec![0; 1024]; - let bytes = stream.read(&mut read_buffer).await?; + let mut read_buffer = Vec::new(); + let bytes = stream.read_to_end(&mut read_buffer).await?; let response = serde_json::from_slice(&read_buffer[..bytes])?; Ok(response) diff --git a/src/ipc/server/mod.rs b/src/ipc/server/mod.rs index 0f944b7..5f210d2 100644 --- a/src/ipc/server/mod.rs +++ b/src/ipc/server/mod.rs @@ -82,8 +82,8 @@ impl Ipc { ) -> Result<()> { let (mut stream_read, mut stream_write) = stream.split(); - let mut read_buffer = vec![0; 1024]; - let bytes = stream_read.read(&mut read_buffer).await?; + let mut read_buffer = Vec::new(); + let bytes = stream_read.read_to_end(&mut read_buffer).await?; // FIXME: Error on invalid command let command = serde_json::from_slice::<Command>(&read_buffer[..bytes])?; ```
Author
Owner

@JakeStanger commented on GitHub (Jun 24, 2025):

Hm, I feel like I'm missing something obvious.

I wonder if calling shutdown on the write stream will do that as desired? Not sure if it'll do that and then also cut off the read stream

https://docs.rs/tokio/latest/tokio/io/trait.AsyncWriteExt.html#method.shutdown

EDIT: The server is already doing that on response. The client isn't though, since the socket is re-used. Not sure without getting a chance to test...

<!-- gh-comment-id:3000736827 --> @JakeStanger commented on GitHub (Jun 24, 2025): Hm, I feel like I'm missing something obvious. I wonder if calling `shutdown` on the write stream will do that as desired? Not sure if it'll do that and then also cut off the read stream https://docs.rs/tokio/latest/tokio/io/trait.AsyncWriteExt.html#method.shutdown EDIT: The server is already doing that on response. The client isn't though, since the socket is re-used. Not sure without getting a chance to test...
Author
Owner

@postsolar commented on GitHub (Jun 24, 2025):

Yeah ChatGPT suggested this too 😅. I tried adding it to client as well, didn't help. Also tried not splitting the stream in the server's code, because there's something in tokio docs implying caveats, but this didn't help either.

<!-- gh-comment-id:3000766074 --> @postsolar commented on GitHub (Jun 24, 2025): Yeah ChatGPT suggested this too 😅. I tried adding it to client as well, didn't help. Also tried not splitting the stream in the server's code, because there's [something in tokio docs](https://docs.rs/tokio/latest/tokio/net/struct.UnixStream.html#method.split) implying caveats, but this didn't help either.
Author
Owner

@JakeStanger commented on GitHub (Jun 24, 2025):

Fixed by using a BufReader on the server/client. Since the JSON message is always one line, it's possible to append a \n and then read until the first \n.

Nevermind. It kinda works, and then jams up after a while :/

<!-- gh-comment-id:3002020193 --> @JakeStanger commented on GitHub (Jun 24, 2025): ~~Fixed by using a `BufReader` on the server/client. Since the JSON message is always one line, it's possible to append a `\n` and then read until the first `\n`.~~ Nevermind. It kinda works, and then jams up after a while :/
Author
Owner

@JakeStanger commented on GitHub (Jul 14, 2025):

Turns out it jammed up because I've got a systemd timer setting variables on a script, and that was using a version of Ironbar without the fix and it didn't like the mismatch...

Fix incoming!

<!-- gh-comment-id:3070827632 --> @JakeStanger commented on GitHub (Jul 14, 2025): Turns out it jammed up because I've got a systemd timer setting variables on a script, and that was using a version of Ironbar without the fix and it didn't like the mismatch... Fix incoming!
Author
Owner

@postsolar commented on GitHub (Jul 14, 2025):

Thank you for fixing this! Now my submap hints fit into the message 😎

Image
<!-- gh-comment-id:3071189974 --> @postsolar commented on GitHub (Jul 14, 2025): Thank you for fixing this! Now my submap hints fit into the message 😎 <img width="403" height="587" alt="Image" src="https://github.com/user-attachments/assets/750b787f-9c61-4306-a37a-5e0aa2d1f6d9" />
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
JakeStanger/ironbar#7361
No description provided.