Repository navigation
Add tool to display emergency log message full-sceen on boot failure. - #28077
Conversation
|
I want to start with a function that fetches the oldest message in the journal and displays it to the console. |
2022bbe to
7bd44d9
Compare
|
@bluca Subsequently, I have to modify it to take over the entire screen, turn it blue, and display the QR code. Howevever, I am currently not getting an output at all, even when i change the PRIORITY to numbers other than 0. Thank you. |
| _cleanup_close_ int fd = -EBADF; | ||
| char * message = first_emerg_boot_message(); | ||
|
|
||
| fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); |
There was a problem hiding this comment.
so for this I think we should not go to /dev/console (which is a magic device that basically points to wherever boot time logs and stuff should go to which can be serial or similar) but the VT subsystem (which is the virtual terminal, i.e. a textual interface to a local physical display device, i.e. no serial), and I think we should not interfere with the usual log/progress output that /dev/console gets. Hence I'd suggest we allocate a full new VT for this, and then switch to that.
(in case you wonder what a VT is, it's this archaic textual display logic that the linux kernel uses to do early boot logging before wayland/x11 take over, and that you can log into via Alt-F2, Alt-F3, …)
i.e. open /dev/tty1 temporarily, then issue the VT_GETSTATE ioctl call on it which tells you which VTs are currently allocated via a bitmask. Look for the first free VT (i.e. determine lowest unset bit, then format /dev/tty%i with it plus one. Then open that, and use that. switch to it via the VT_ACTIVATE ioctl, then clear it by output ANSI_HOME_CLEAR on it, then display the message there.
If this sounds like a bit much, grep our sources for VT_GETSTAT, we already call that ioctl elsewhere for other reasons.
There was a problem hiding this comment.
VT_OPENQRY might be easier than VT_GETSTATE and __builtin_ctz(~vt_stat.v_state) or whatever.
|
I read that the APIs return errno-style errors on failure. Kindly review my choice of error types sir. I made some of the requested changes. I still have the But I don't want to miss the chance of getting a review in case you view the PR, so I decided to push some first. |
|
I looked up the format string and format value macros sir, and I've now used them in the patch. So it's VT I need to look up now. perhaps I have too many log messages? |
|
Now, we need to register this service as a varlink API client that subscribes to journald to get notified when messages with log_level "emerg" are processed, so it can fetch the message and display it. I've been stuck on implementing this subscribe feature in journald. Please could I get some high level guidance - not so high level, or some resources or docs recommendations? Thank you sirs. |
|
@bluca, Have you been in touch with Poettering though? I looked the the PRs -open and closed ones, It looks like he hasn't been with us for over a week. Did he go on vacation without inviting us or at least share photos? I'm sort of bothered I've been on just one of the 4 points from his last guidance for over 2 weeks. Thank you. |
|
there's a merge conflict, needs a rebase |
|
okay sir. |
|
|
||
| xsprintf(tty, "/dev/tty%d", free_vt + 1); | ||
|
|
||
| fd = open_terminal(tty, O_RDWR|O_NOCTTY|O_CLOEXEC); |
There was a problem hiding this comment.
You leak tty1's
fdhere
😂😂
You remember me from that initrd guide you gave in May?
Thanks again for that.
Thanks for showing up here too.
|
Looks like I'm hearing you say "tty1's fd should be closed before we assign fd to hold the descriptor of another tty" doesn't |
| fd_tty1 = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC); | ||
| if (fd_tty1 < 0) | ||
| return log_error_errno(fd, "Failed to open tty1: %m"); | ||
|
|
||
| r = find_next_free_vt(fd_tty1, &free_vt, &original_vt); | ||
| if (r < 0) | ||
| return log_error_errno(r, "Failed to find a free VT: %m"); | ||
|
|
||
| xsprintf(tty, "/dev/tty%d", free_vt + 1); | ||
|
|
||
| fd = open_terminal(tty, O_RDWR|O_NOCTTY|O_CLOEXEC); |
The {
_cleanup_close_ void* int fd = -EBADF;
fd = open(...); /* fd = 4 */
fd = open(...); /* fd = 5 */
/* we're about to leave the block... compiler adds: */ close(fd)
}Notice that in the above code, What you want to do is something like this: {
_cleanup_close_ void* int fd = -EBADF;
fd = open(...); /* fd = 4 */
close(fd) /* we close fd 4, since we're about to replace it with fd 5, which will get auto-closed when we leave the block */
fd = open(...); /* fd = 5 */
/* we're about to leave the block... compiler adds: */ close(fd)
}That is what |
| if (tty1_fd < 0) | ||
| return log_error_errno(fd, "Failed to open tty1: %m"); | ||
|
|
||
| close_and_replace(fd, tty1_fd); |
There was a problem hiding this comment.
Wrong place!
Basically where you put it now, you close fd (which is already -EBADF, so closing it does nothing). Then you replace fd with tty1_fd (and at the same time you make tty1_fd = -EBADF). Then later you overwrite fd with the real value you want, and so you're still leaking.
What you really want to do is something like this:
_cleanup_close int fd = -EBADF;
int r;
fd = open_terminal("/dev/tty1", ...);
if (fd < 0) ...
...
r = open_terminal(tty, ...)
if (r < 0) ...
close_and_replace(fd, r) /* this closes fd (which is /dev/tty1) and replaces it with r (which is the tty you want) */PS: also, both fd and tty1_fd have _cleanup_close_ attached to them. Not sure if that's intended or not.
|
Wow... awesome. Thanks again. Let me fix. |
|
hey @AdrianVovk, I found you do actually have some business in college, although not actually as a professor. Please let me know if your schedule has room for some sort of extra friend. |
|
Thank you @yuwata for the detailed review. |
|
@yuwata, I have made all the requested changes. |
|
Thank you so much @yuwata for the very detailed review. |
|
@yuwata, I made all the requested changes. |
|
needs a rebase on main due to conflicts |
Okay sir. |
yuwata
left a comment
There was a problem hiding this comment.
LGTM. Let's go in this form at least now.
Future tasks are
- merge two qrcode logic more,
- add tests for bsod.service.
|
When you rebase and push, please also amend the commit message, as this is not about PID1, it's a different tool |
Certainly sir. |
Alright sir. |
No description provided.