diff options
author | Jaroslav Kysela <perex@perex.cz> | 2022-02-01 20:45:27 +0100 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2022-02-01 20:45:48 +0100 |
commit | 64fa37f09b29a7675246a36361e25fd218ab7852 (patch) | |
tree | 9728e3daa30f9850c9e61bff396a4f26cd3df176 /alsactl | |
parent | ccb6d4612bdfeb2b68c118549a9e717489f5d70c (diff) | |
download | alsa-utils-64fa37f09b29a7675246a36361e25fd218ab7852.tar.gz |
alsactl: lock - use alarm signal and F_SETLKW rather polling
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'alsactl')
-rw-r--r-- | alsactl/lock.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/alsactl/lock.c b/alsactl/lock.c index aa77254..0238e95 100644 --- a/alsactl/lock.c +++ b/alsactl/lock.c @@ -27,15 +27,26 @@ #include <fcntl.h> #include <errno.h> #include <string.h> +#include <signal.h> +#include <sys/time.h> #include <sys/stat.h> #include "alsactl.h" +static int alarm_flag; + +static void signal_handler_alarm(int sig) +{ + alarm_flag = 1; +} + static int state_lock_(int lock, int timeout, int _fd) { int fd = -1, err = 0; struct flock lck; struct stat st; char lcktxt[14]; + struct sigaction sig_alarm, sig_alarm_orig; + struct itimerval itv; char *nfile = lockfile; if (do_lock <= 0) @@ -93,15 +104,31 @@ static int state_lock_(int lock, int timeout, int _fd) goto out; } } - while (timeout > 0) { - if (fcntl(fd, F_SETLK, &lck) < 0) { - sleep(1); - timeout--; - } else { + alarm_flag = 0; + memset(&sig_alarm, 0, sizeof(sig_alarm)); + sigemptyset(&sig_alarm.sa_mask); + sig_alarm.sa_handler = signal_handler_alarm; + if (sigaction(SIGALRM, &sig_alarm, &sig_alarm_orig) < 0) { + err = -ENXIO; + goto out; + } + memset(&itv, 0, sizeof(itv)); + itv.it_value.tv_sec = timeout; + if (setitimer(ITIMER_REAL, &itv, NULL) < 0) { + err = -ENXIO; + sigaction(SIGALRM, &sig_alarm_orig, NULL); + goto out; + } + while (alarm_flag == 0) { + if (fcntl(fd, F_SETLKW, &lck) == 0) break; - } + if (errno == EAGAIN || errno == ERESTART) + continue; } - if (timeout <= 0) { + memset(&itv, 0, sizeof(itv)); + setitimer(ITIMER_REAL, &itv, NULL); + sigaction(SIGALRM, &sig_alarm_orig, NULL); + if (alarm_flag) { err = -EBUSY; goto out; } |