alsactl_CFLAGS=$(AM_CFLAGS) -D__USE_GNU \
-DSYS_ASOUNDRC=\"$(ASOUND_STATE_DIR)/asound.state\" \
- -DSYS_LOCKFILE=\"$(ASOUND_LOCK_DIR)/asound.state.lock\" \
+ -DSYS_LOCKPATH=\"$(ASOUND_LOCK_DIR)\" \
+ -DSYS_LOCKFILE=\"asound.state.lock\" \
-DSYS_PIDFILE=\"$(ALSACTL_PIDFILE_DIR)/alsactl.pid\"
noinst_HEADERS=alsactl.h list.h init_sysdeps.c init_utils_string.c \
int use_syslog = 0;
char *command;
char *statefile = NULL;
+char *lockpath = SYS_LOCKPATH;
char *lockfile = SYS_LOCKFILE;
#define TITLE 0x0100
{ FILEARG | 'a', "config-dir", "boot / hotplug configuration directory (default " SYS_ASOUND_DIR ")" },
{ 'l', "lock", "use file locking to serialize concurrent access" },
{ 'L', "no-lock", "do not use file locking to serialize concurrent access" },
+{ FILEARG | 'K', "lock-dir", "lock path (default " SYS_LOCKPATH ")" },
{ FILEARG | 'O', "lock-state-file", "state lock file path (default " SYS_LOCKFILE ")" },
{ 'F', "force", "try to restore the matching controls as much as possible" },
{ 0, NULL, " (default mode)" },
case 'L':
do_lock = -1;
break;
+ case 'K':
+ lockpath = optarg;
+ break;
case 'O':
lockfile = optarg;
break;
#include <stdbool.h>
#include <alsa/asoundlib.h>
+#define LOCK_TIMEOUT 10
+
extern int debugflag;
extern int force_restore;
extern int ignore_nocards;
extern int use_syslog;
extern char *command;
extern char *statefile;
+extern char *lockpath;
extern char *lockfile;
struct snd_card_iterator {
int init(const char *cfgdir, const char *file, int flags, const char *cardname);
int init_ucm(int flags, int cardno);
int state_lock(const char *file, int timeout);
-int state_unlock(int fd, const char *file);
+int state_unlock(int lock_fd, const char *file);
+int card_lock(int card_number, int timeout);
+int card_unlock(int lock_fd, int card_number);
int save_state(const char *file, const char *cardname);
int load_state(const char *cfgdir, const char *file,
const char *initfile, int initflags,
#include <sys/stat.h>
#include "alsactl.h"
+#define PATH_SIZE 512
+
static int alarm_flag;
static void signal_handler_alarm(int sig)
alarm_flag = 1;
}
-static int state_lock_(int lock, int timeout, int _fd)
+static int state_lock_(const char *lock_file, int lock, int timeout, int _fd)
{
int fd = -1, err = 0;
struct flock lck;
char lcktxt[14];
struct sigaction sig_alarm, sig_alarm_orig;
struct itimerval itv;
- char *nfile = lockfile;
if (do_lock <= 0)
return 0;
fd = _fd;
}
while (fd < 0 && timeout-- > 0) {
- fd = open(nfile, O_RDWR);
+ fd = open(lock_file, O_RDWR);
if (!lock && fd < 0) {
err = -EIO;
goto out;
}
if (fd < 0) {
- fd = open(nfile, O_RDWR|O_CREAT|O_EXCL, 0644);
+ fd = open(lock_file, O_RDWR|O_CREAT|O_EXCL, 0644);
if (fd < 0) {
if (errno == EBUSY || errno == EAGAIN) {
sleep(1);
continue;
}
if (errno == EEXIST) {
- fd = open(nfile, O_RDWR);
+ fd = open(lock_file, O_RDWR);
if (fd >= 0)
break;
}
return err;
}
+static void state_lock_file(char *buf, size_t buflen)
+{
+ if (lockfile[0] == '/')
+ snprintf(buf, buflen, "%s", lockfile);
+ else
+ snprintf(buf, buflen, "%s/%s", lockpath, lockfile);
+}
+
int state_lock(const char *file, int timeout)
{
+ char fn[PATH_SIZE];
int err;
- err = state_lock_(1, timeout, -1);
+ state_lock_file(fn, sizeof(fn));
+ err = state_lock_(fn, 1, timeout, -1);
if (err < 0)
error("file %s lock error: %s", file, strerror(-err));
return err;
int state_unlock(int _fd, const char *file)
{
+ char fn[PATH_SIZE];
int err;
- err = state_lock_(0, 10, _fd);
+ state_lock_file(fn, sizeof(fn));
+ err = state_lock_(fn, 0, 10, _fd);
if (err < 0)
error("file %s unlock error: %s", file, strerror(-err));
return err;
}
+
+static void card_lock_file(char *buf, size_t buflen, int card_number)
+{
+ snprintf(buf, buflen, "%s/card%i.lock", lockpath, card_number);
+}
+
+int card_lock(int card_number, int timeout)
+{
+ char fn[PATH_SIZE];
+ int err;
+
+ card_lock_file(fn, sizeof(fn), card_number);
+ err = state_lock_(fn, 1, timeout, -1);
+ if (err < 0)
+ error("card %d lock error: %s", card_number, strerror(-err));
+ return err;
+}
+
+int card_unlock(int _fd, int card_number)
+{
+ char fn[PATH_SIZE];
+ int err;
+
+ card_lock_file(fn, sizeof(fn), card_number);
+ err = state_lock_(fn, 0, 10, _fd);
+ if (err < 0)
+ error("card %d unlock error: %s", card_number, strerror(-err));
+ return err;
+}
}
strcpy(nfile, file);
strcat(nfile, ".new");
- lock_fd = state_lock(file, 10);
+ lock_fd = state_lock(file, LOCK_TIMEOUT);
if (lock_fd < 0) {
err = lock_fd;
goto out;
const char *initfile, int initflags,
const char *cardname, int do_init)
{
- int err, finalerr = 0, open_failed;
+ int err, finalerr = 0, open_failed, lock_fd;
struct snd_card_iterator iter;
snd_config_t *config;
const char *cardname1;
while ((cardname1 = snd_card_iterator_next(&iter)) != NULL) {
if (!do_init)
break;
+ lock_fd = card_lock(iter.card, LOCK_TIMEOUT);
+ if (lock_fd < 0) {
+ finalerr = lock_fd;
+ initfailed(iter.card, "lock", err);
+ continue;
+ }
err = init(cfgdir, initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname1);
+ card_unlock(lock_fd, iter.card);
if (err < 0) {
finalerr = err;
initfailed(iter.card, "init", err);
if (err < 0)
goto out;
while ((cardname1 = snd_card_iterator_next(&iter)) != NULL) {
+ lock_fd = card_lock(iter.card, LOCK_TIMEOUT);
+ if (lock_fd < 0) {
+ initfailed(iter.card, "lock", lock_fd);
+ finalerr = lock_fd;
+ continue;
+ }
/* error is ignored */
init_ucm(initflags | FLAG_UCM_FBOOT, iter.card);
/* do a check if controls matches state file */
finalerr = err;
initfailed(iter.card, "restore", err);
}
+ card_unlock(lock_fd, iter.card);
}
err = finalerr ? finalerr : snd_card_iterator_error(&iter);
out:
if (stdio_flag) {
err = snd_input_stdio_attach(&in, stdin, 0);
} else {
- lock_fd = state_lock(file, 10);
+ lock_fd = state_lock(file, LOCK_TIMEOUT);
err = lock_fd >= 0 ? snd_input_stdio_open(&in, file, "r") : lock_fd;
}
if (err < 0) {