What I'm trying to do
I am trying to make myself a modular statusbar for dwm
, like i3blocks
. In short the statusbar will consist of fundamental units called blocks, each of which represent a command.
For example, in the statusbar shown below, each section separated by arrowheads "<" is a block.
The idea is to have each of them update independently with some interval.
I could go for synchronous updation of the blocks but I don't want to because some of the scripts in my statusbar take ~5 seconds to execute which stalls the other modules during that period, and I'm hoping to avoid that. This is really noticeable when I boot up my PC and nothing shows up on my statusbar for ~5 seconds because one module just takes forever to execute.
What I've tried
I have tried using pthread.h
but I thought of abandoning that approach because using a thread per module seemed like a bad idea and even i3blocks
doesn't use it.
I used fork()
also only to find out that I couldn't modify the parent's global variables from within the child process.
I researched online and found out that I could use pipes to make the child process communicate with the parent, but all my efforts were in vain as reading a pipe using read()
blocks the parent's flow of control replicating the same sequential behaviour as earlier.
This is the code where I want to make asynchronous calls to the function getCommand
:
void getCommands(int time) {
int pipes[len(blocks)][2];
for (int i = 0; i < len(blocks); i++) {
if (pipe(pipes[i]) == -1) {
printf("Pipe failed\n");
exit(1);
}
const Block *current = blocks + i;
if (time == 0 || (current->interval != 0 && time % current->interval == 0)) {
if (fork() == 0) {
getCommand(current, statusbar[i]);
close(pipes[i][0]);
write(pipes[i][1], statusbar[i], strlen(statusbar[i]));
close(pipes[i][1]);
exit(0);
} else {
close(pipes[i][1]);
read(pipes[i][0], statusbar[i], CMDLENGTH);
close(pipes[i][0]);
}
}
}
}
The rest of the code is on my GitHub repository: UtkarshVerma/dwmblocks
tl;dr
I want to know how to make asynchronous calls to functions with a callback. The function should be able to modify global variables as well.
Thanks in advance.
UpdateThis is my first time writing a software in C, therefore suggestions of any kind on the code are welcome.
I think I have made some progress finally. Here is what I am doing. I execute the commands in a fork, and then watch out for SIGCHLD on the parent. In the SIGCHLD handler, I then read all pipes to the child forks in a non-blocking manner to check if the buffer is non-empty. This works really well except for one caveat. The parent can never tell if the executed command had blank output. I made a hacky attempt like this, but I'm curious if this can be handled more appropriately.