i3blocks
i3blocks copied to clipboard
xtitle -s hangs from time to time
xtitle -s -t 30
runs fine in a terminal, but in i3blocks it will eventually just freeze in some window title and not update itself any longer, requiring i3 to be restarted.
Another one is having the same issue: https://www.reddit.com/r/i3wm/comments/fsf26n/xtitle_in_i3blocks_hangs_in_bar/
My config: [title] command=xtitle -s -t 30 interval=persist
I can confirm I'm having the same issue as well.
Running NixOS:
$ uname -a
Linux hostname 5.6.7-hardened #1-NixOS SMP Thu Apr 23 08:38:27 UTC 2020 x86_64 GNU/Linux
Interestingly, it seems to happen when switching tabs in Firefox. xtitle
doesn't seem to be the problem since when run in a terminal it works fine, however after switching tabs in Firefox once or twice the xtitle -s
configuration of my block simply... stops updating.
My full ~/.i3blocks.conf
:
separator_block_width=30
command=~/bin/blocks/$BLOCK_NAME < /dev/null
markup=pango
[current-window]
command=xtitle -s
interval=persist
[bluetooth]
interval=60
signal=6
[wifi]
interval=15
signal=5
[battery]
interval=60
signal=4
[brightness]
interval=60
signal=2
[volume]
interval=60
signal=3
[redshift]
interval=120
[time]
interval=1
[hostname]
command=hostname
interval=once
Interestingly the Firefox output from xtitle -s
is doubled, like so (switching between two tabs):
xtitle -s hangs from time to time · Issue #422 · vivien/i3blocks - Firefox Developer Edition
xtitle -s hangs from time to time · Issue #422 · vivien/i3blocks - Firefox Developer Edition
vivien/i3blocks: A feed generator for text based status bars - Firefox Developer Edition
vivien/i3blocks: A feed generator for text based status bars - Firefox Developer Edition
However, other windows don't display doubled output.
Try the following.
However this whole thing is extremely fragile. If blocklet does not write the whole line at once, race condition may occur and parts of the line may get lost. Forever.
diff --git a/block.c b/block.c
index c24fb0a..d94ff25 100644
--- a/block.c
+++ b/block.c
@@ -94,18 +94,12 @@ static int block_stdout(struct block *block)
const char *label, *full_text;
int out = block->out[0];
char buf[BUFSIZ];
- size_t count;
int err;
- if (block->interval == INTERVAL_PERSIST)
- count = 1;
- else
- count = -1; /* SIZE_MAX */
-
if (block->format == FORMAT_JSON)
- err = json_read(out, count, block->env);
+ err = json_read(out, -1, block->env);
else
- err = i3bar_read(out, count, block->env);
+ err = i3bar_read(out, -1, block->env);
if (err && err != -EAGAIN)
return err;
The pull request #425 fixes the issues I had with xtitle
The PR works indeed, thanks!
Happens for me too.
please merge! Works for me too
Use unbuffer xtitle -s
(from the expect
package). It’s the only thing that works for me.
Another workaround (requires python-i3ipc):
blocks/title
#!/usr/bin/env python
import i3ipc
def print_window_title(container):
print(container.name if container.name is not None else "", flush=True)
def on_window_focus(i3, e):
print_window_title(e.container)
i3 = i3ipc.Connection()
print_window_title(i3.get_tree().find_focused())
i3.on("window::focus", on_window_focus)
i3.main()
i3blocks.conf
:
[title]
command=blocks/title
interval=persist
I've got this in my config and no combination of unbuffer
/stdbuf
/etc. keeps it from eventually getting stuck.
[active]
command=unbuffer swaymsg -t subscribe -m '["window"]' | jq --unbuffered -r 'select(.change=="focus" or .container.focused == true) | .container.name'
interval=persist
It's a shame this repo seems completely abandoned ...
no combination of unbuffer/stdbuf/etc. keeps it from eventually getting stuck.
Yes, as I have said above there is no external workaround for this. If your program produces input faster or slower than i3blocks
can read the lines, it breaks. No magical buffering mode exists. (Please do not waste your time.)
And again, it is not because xtitle
does not flush its output. It flushes everything at the end of the line, so no characters get stuck at the side of xtitle
that would require you to use no buffering.
https://github.com/baskerville/xtitle/blob/6f46584fe4ba2763438231e6cce5b180f5ca9c0e/xtitle.c#L212
So every "workaround" that replaces xtitle
–and “hey guys it works”–makes no sense. Or at most a false sense of everything working correctly, because it is the same sh** than it was before.
Please merge this PR https://github.com/vivien/i3blocks/pull/425 ! Works for me too.
It seems like xtitle
flushes multiple lines at once, while i3blocks arguably expects one line at a time for persistent blocks, like what line buffered programs such as echo
or printf
shell commands do. We can reproduce the issue with a program like this:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int l = 0;
for (;;) {
l++;
fprintf(stderr, "line %d\n", l);
fprintf(stdout, "line %d\n", l);
l++;
fprintf(stderr, "line %d\n", l);
fprintf(stdout, "line %d\n", l);
l++;
fprintf(stderr, "line %d\n", l);
fprintf(stdout, "line %d\n", l);
fflush(stdout);
sleep(3);
}
return 0;
}
Here only one signal is sent every 3 lines. The first issue is that we get out of sync between what the block prints and what the bar displays. It may look correct because i3blocks will iterate over the lines and print "line 1", then "line 2", etc., while in fact we may expect to see "line 3", then "line 6", etc.
The second issue is that because 3 lines come in, but only one comes out, lines accumulate in the pipe until it eventually gets full (usually 65536 bytes long). Because we write more that we read, we will eventually block on a call to flush after a while. This is the issue encountered in #450 and #451.
The workaround for this as of 1.5 is to ensure that the program is line buffered or manually flushes one line at a time, otherwise we may pace its output ourselves for example with <command> | while read line ; do echo $line ; done
. Line buffering can be changed externally with stdbuf -oL <command>
but this won't work if the command tweaks its buffering mode itself.
That said, the only requirement we have for a block command is to provide newline terminated output, since it is the only reliable boundary that a program can provide to delimit the data to be used. Relying on incomplete lines or when the data is received is simply error prone. @zsugabubus actually had a good guess about draining the output, but the suggested PR has a few concerns so I will push a fix soon. Thanks guys for your patience on the issue!