Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to wait for command to finish #7

Merged
merged 3 commits into from
Jan 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 22 additions & 29 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct swayidle_state {
struct wl_event_loop *event_loop;
struct wl_list timeout_cmds; // struct swayidle_timeout_cmd *
char *lock_cmd;
bool wait;
} state;

struct swayidle_timeout_cmd {
Expand Down Expand Up @@ -83,7 +84,9 @@ static void cmd_exec(char *param) {
swayidle_log(LOG_DEBUG, "Cmd exec %s", param);
pid_t pid = fork();
if (pid == 0) {
pid = fork();
if (!state.wait) {
pid = fork();
}
if (pid == 0) {
char *const cmd[] = { "sh", "-c", param, NULL, };
execvp(cmd[0], cmd);
Expand All @@ -104,18 +107,8 @@ static void cmd_exec(char *param) {

#if HAVE_SYSTEMD || HAVE_ELOGIND
static int lock_fd = -1;
static int ongoing_fd = -1;
static struct sd_bus *bus = NULL;

static int release_lock(void *data) {
swayidle_log(LOG_INFO, "Releasing sleep lock %d", ongoing_fd);
if (ongoing_fd >= 0) {
close(ongoing_fd);
}
ongoing_fd = -1;
return 0;
}

static void acquire_sleep_lock(void) {
sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
Expand All @@ -127,29 +120,27 @@ static void acquire_sleep_lock(void) {
if (ret < 0) {
swayidle_log(LOG_ERROR,
"Failed to send Inhibit signal: %s", error.message);
sd_bus_error_free(&error);
return;
goto cleanup;
}

ret = sd_bus_message_read(msg, "h", &lock_fd);
if (ret < 0) {
errno = -ret;
swayidle_log_errno(LOG_ERROR,
"Failed to parse D-Bus response for Inhibit");
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
return;
} else {
swayidle_log(LOG_INFO, "Got sleep lock: %d", lock_fd);
goto cleanup;
}

// sd_bus_message_unref closes the file descriptor so we need
// to copy it beforehand
lock_fd = fcntl(lock_fd, F_DUPFD_CLOEXEC, 3);
if (lock_fd < 0) {
swayidle_log(LOG_ERROR, "Failed to copy sleep lock fd");
if (lock_fd >= 0) {
swayidle_log(LOG_INFO, "Got sleep lock: %d", lock_fd);
} else {
swayidle_log_errno(LOG_ERROR, "Failed to copy sleep lock fd");
}

cleanup:
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
}
Expand All @@ -170,19 +161,17 @@ static int prepare_for_sleep(sd_bus_message *msg, void *userdata,
return 0;
}

ongoing_fd = lock_fd;

if (state.lock_cmd) {
cmd_exec(state.lock_cmd);
}
swayidle_log(LOG_DEBUG, "Prepare for sleep done");

if (ongoing_fd >= 0) {
struct wl_event_source *source =
wl_event_loop_add_timer(state.event_loop, release_lock, NULL);
wl_event_source_timer_update(source, 1000);
swayidle_log(LOG_INFO, "Releasing sleep lock %d", lock_fd);
if (lock_fd >= 0) {
close(lock_fd);
}
lock_fd = -1;

swayidle_log(LOG_DEBUG, "Prepare for sleep done");
return 0;
}

Expand Down Expand Up @@ -371,16 +360,20 @@ static int parse_sleep(int argc, char **argv) {

static int parse_args(int argc, char *argv[]) {
int c;
while ((c = getopt(argc, argv, "hd")) != -1) {
while ((c = getopt(argc, argv, "hdw")) != -1) {
switch (c) {
case 'd':
verbosity = LOG_DEBUG;
break;
case 'w':
state.wait = true;
break;
case 'h':
case '?':
printf("Usage: %s [OPTIONS]\n", argv[0]);
printf(" -d\tdebug\n");
printf(" -h\tthis help menu\n");
printf(" -d\tdebug\n");
printf(" -w\twait for command to finish\n");
return 1;
default:
return 1;
Expand Down
10 changes: 10 additions & 0 deletions swayidle.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ swayidle - Idle manager for Wayland
*-d*
Enable debug output.

*-w*
Wait for command to finish executing before continuing, helpful for ensuring
that a *before-sleep* command has finished before the system goes to sleep.

Note: using this option causes swayidle to block until the command finishes.

# DESCRIPTION

swayidle listens for idle activity on your Wayland compositor and executes tasks
Expand All @@ -36,6 +42,10 @@ Sending SIGUSR1 to swayidle will immediately enter idle state.
If built with systemd support, executes _command_ before systemd puts the
computer to sleep.

Note: this only delays sleeping up to the limit set in *logind.conf(5)* by
the option InhibitDelayMaxSec. A command that has not finished by then will
continue running after resuming from sleep.

All commands are executed in a shell.

# EXAMPLE
Expand Down