From 64fa37f09b29a7675246a36361e25fd218ab7852 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 1 Feb 2022 20:45:27 +0100 Subject: alsactl: lock - use alarm signal and F_SETLKW rather polling Signed-off-by: Jaroslav Kysela --- alsactl/lock.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'alsactl') 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 #include #include +#include +#include #include #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; } -- cgit v1.2.1