summaryrefslogtreecommitdiff
path: root/alsactl
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2022-02-01 20:45:27 +0100
committerJaroslav Kysela <perex@perex.cz>2022-02-01 20:45:48 +0100
commit64fa37f09b29a7675246a36361e25fd218ab7852 (patch)
tree9728e3daa30f9850c9e61bff396a4f26cd3df176 /alsactl
parentccb6d4612bdfeb2b68c118549a9e717489f5d70c (diff)
downloadalsa-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.c41
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;
}