mirror of
https://github.com/mintycube/dwmblocks.git
synced 2024-10-22 14:05:47 +02:00
Ensure that only one execution happens per block at an instance
This commit is contained in:
parent
0bc49aa703
commit
0471144a2e
56
main.c
56
main.c
@ -10,11 +10,13 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define POLL_INTERVAL 50
|
|
||||||
#define LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
#define MAX(a, b) (a > b ? a : b)
|
#define MAX(a, b) (a > b ? a : b)
|
||||||
|
|
||||||
|
#define POLL_INTERVAL 50
|
||||||
#define BLOCK(cmd, interval, signal) \
|
#define BLOCK(cmd, interval, signal) \
|
||||||
{ "echo \"$(" cmd ")\"", interval, signal }
|
{ "echo \"$(" cmd ")\"", interval, signal }
|
||||||
|
|
||||||
typedef const struct {
|
typedef const struct {
|
||||||
const char* command;
|
const char* command;
|
||||||
const unsigned int interval;
|
const unsigned int interval;
|
||||||
@ -47,6 +49,7 @@ static int pipes[LEN(blocks)][2];
|
|||||||
static int timerPipe[2];
|
static int timerPipe[2];
|
||||||
static int signalFD;
|
static int signalFD;
|
||||||
static int epollFD;
|
static int epollFD;
|
||||||
|
static unsigned int execLock = 0;
|
||||||
void (*writeStatus)();
|
void (*writeStatus)();
|
||||||
|
|
||||||
int gcd(int a, int b) {
|
int gcd(int a, int b) {
|
||||||
@ -65,14 +68,19 @@ void closePipe(int* pipe) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void execBlock(int i, const char* button) {
|
void execBlock(int i, const char* button) {
|
||||||
|
// Ensure only one child process exists per block at an instance
|
||||||
|
if (execLock & 1 << i)
|
||||||
|
return;
|
||||||
|
// Lock execution of block until current instance finishes execution
|
||||||
|
execLock |= 1 << i;
|
||||||
|
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
close(pipes[i][0]);
|
close(pipes[i][0]);
|
||||||
dup2(pipes[i][1], STDOUT_FILENO);
|
dup2(pipes[i][1], STDOUT_FILENO);
|
||||||
|
|
||||||
if (button)
|
if (button)
|
||||||
setenv("BLOCK_BUTTON", button, 1);
|
setenv("BLOCK_BUTTON", button, 1);
|
||||||
execl("/bin/sh", "sh", "-c", blocks[i].command);
|
execl("/bin/sh", "sh", "-c", blocks[i].command, (char*)NULL);
|
||||||
close(pipes[i][1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,11 +111,6 @@ void updateBlock(int i) {
|
|||||||
char buffer[LEN(outputs[0]) - CLICKABLE_BLOCKS];
|
char buffer[LEN(outputs[0]) - CLICKABLE_BLOCKS];
|
||||||
int bytesRead = read(pipes[i][0], buffer, LEN(buffer));
|
int bytesRead = read(pipes[i][0], buffer, LEN(buffer));
|
||||||
|
|
||||||
if (bytesRead == 1) {
|
|
||||||
output[0] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim UTF-8 characters properly
|
// Trim UTF-8 characters properly
|
||||||
int j = bytesRead - 1;
|
int j = bytesRead - 1;
|
||||||
while ((buffer[j] & 0b11000000) == 0x80)
|
while ((buffer[j] & 0b11000000) == 0x80)
|
||||||
@ -127,13 +130,16 @@ void updateBlock(int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if CLICKABLE_BLOCKS
|
#if CLICKABLE_BLOCKS
|
||||||
if (blocks[i].signal > 0) {
|
if (bytesRead > 1 && blocks[i].signal > 0) {
|
||||||
output[0] = blocks[i].signal;
|
output[0] = blocks[i].signal;
|
||||||
output++;
|
output++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strcpy(output, buffer);
|
strcpy(output, buffer);
|
||||||
|
|
||||||
|
// Remove execution lock for the current block
|
||||||
|
execLock &= ~(1 << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug() {
|
void debug() {
|
||||||
@ -206,14 +212,17 @@ void setupSignals() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void statusLoop() {
|
void statusLoop() {
|
||||||
while (statusContinue) {
|
// Poll every `POLL_INTERVAL` milliseconds
|
||||||
int eventCount = epoll_wait(epollFD, events, LEN(events), POLL_INTERVAL / 10);
|
const struct timespec pollInterval = {.tv_nsec = POLL_INTERVAL * 1000000L};
|
||||||
|
struct timespec toSleep = pollInterval;
|
||||||
|
|
||||||
|
while (statusContinue) {
|
||||||
|
int eventCount = epoll_wait(epollFD, events, LEN(events), 1);
|
||||||
for (int i = 0; i < eventCount; i++) {
|
for (int i = 0; i < eventCount; i++) {
|
||||||
unsigned int id = events[i].data.u32;
|
unsigned int id = events[i].data.u32;
|
||||||
|
|
||||||
if (id == LEN(blocks)) {
|
if (id == LEN(blocks)) {
|
||||||
unsigned long long int j = 0;
|
unsigned int j = 0;
|
||||||
read(timerPipe[0], &j, sizeof(j));
|
read(timerPipe[0], &j, sizeof(j));
|
||||||
execBlocks(j);
|
execBlocks(j);
|
||||||
} else if (id < LEN(blocks)) {
|
} else if (id < LEN(blocks)) {
|
||||||
@ -222,12 +231,13 @@ void statusLoop() {
|
|||||||
signalHandler();
|
signalHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (eventCount)
|
if (eventCount != -1)
|
||||||
writeStatus();
|
writeStatus();
|
||||||
|
|
||||||
// Poll every `POLL_INTERVAL` milliseconds
|
// Sleep for `pollInterval` even on being interrupted
|
||||||
struct timespec toSleep = {.tv_nsec = POLL_INTERVAL * 1000000UL};
|
while (nanosleep(&toSleep, &toSleep) == -1)
|
||||||
nanosleep(&toSleep, &toSleep);
|
;
|
||||||
|
toSleep = pollInterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,18 +257,16 @@ void timerLoop() {
|
|||||||
struct timespec toSleep = sleepTime;
|
struct timespec toSleep = sleepTime;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// Sleep for `sleepTime` even on being interrupted
|
|
||||||
if (nanosleep(&toSleep, &toSleep) == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Notify parent to update blocks
|
// Notify parent to update blocks
|
||||||
write(timerPipe[1], &i, sizeof(i));
|
write(timerPipe[1], &i, sizeof(i));
|
||||||
|
|
||||||
// After sleep, reset timer and update counter
|
// Wrap `i` to the interval [1, `maxInterval`]
|
||||||
toSleep = sleepTime;
|
|
||||||
|
|
||||||
// Wrap `i` to the interval [1, maxInterval]
|
|
||||||
i = (i + sleepInterval - 1) % maxInterval + 1;
|
i = (i + sleepInterval - 1) % maxInterval + 1;
|
||||||
|
|
||||||
|
// Sleep for `sleepTime` even on being interrupted
|
||||||
|
while (nanosleep(&toSleep, &toSleep) == -1)
|
||||||
|
;
|
||||||
|
toSleep = sleepTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(timerPipe[1]);
|
close(timerPipe[1]);
|
||||||
|
Loading…
Reference in New Issue
Block a user