diff --git a/src/builder/b-deletion.c b/src/builder/b-deletion.c
index 0690e4e..8bfa236 100644
--- a/src/builder/b-deletion.c
+++ b/src/builder/b-deletion.c
@@ -24,6 +24,7 @@
#include <signal.h>
#include <limits.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <sys/types.h>
#if !defined(WIN32)
@@ -54,10 +55,6 @@
#include "b-private.h"
-extern int
-saib_suspender_fork(void);
-extern struct lws_protocols protocol_suspender_stdxxx;
-
int
sai_deletion_worker(const char *home_dir)
{
@@ -268,6 +265,9 @@ saib_deletion_init(const char *argv0)
return 1;
}
+ fcntl(pfd[0], F_SETFD, FD_CLOEXEC);
+ fcntl(pfd[1], F_SETFD, FD_CLOEXEC);
+
pid = fork();
if (pid == -1) {
lwsl_err("fork() failed\n");
diff --git a/src/builder/b-power.c b/src/builder/b-power.c
index 97b130b..2193de2 100644
--- a/src/builder/b-power.c
+++ b/src/builder/b-power.c
@@ -195,8 +195,16 @@ LWS_SS_USER_TYPEDEF
static lws_ss_state_return_t
saib_power_link_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
{
+#if !defined(WIN32)
uint8_t te = 0;
ssize_t n;
+#if defined(__linux__)
+ int fd = lws_spawn_get_fd_stdxxx(lsp_suspender, 0);
+#endif
+#if defined(__APPLE__)
+ int fd = builder.pipe_suspender_wr;
+#endif
+
if (len < 4 || !(flags & LWSSS_FLAG_SOM))
return 0;
@@ -217,10 +225,10 @@ saib_power_link_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
* cleanly
*/
- n = write(lws_spawn_get_fd_stdxxx(lsp_suspender, 0), &te, 1);
+ n = write(fd, &te, 1);
if (n != 1)
lwsl_err("%s: unable to request shutdown\n", __func__);
-
+#endif
return LWSSSSRET_OK;
}
@@ -235,10 +243,16 @@ sul_do_suspend_cb(lws_sorted_usec_list_t *sul)
#if !defined(WIN32)
uint8_t te = 1;
ssize_t n;
+#if defined(__linux__)
+ int fd = lws_spawn_get_fd_stdxxx(lsp_suspender, 0);
+#endif
+#if defined(__APPLE__)
+ int fd = builder.pipe_suspender_wr;
+#endif
lwsl_notice("%s: actioning suspend...\n", __func__);
- n = write(lws_spawn_get_fd_stdxxx(lsp_suspender, 0), &te, 1);
+ n = write(fd, &te, 1);
if (n == 1) {
#if defined(WIN32)
Sleep(2000);
@@ -358,3 +372,16 @@ saib_power_init(void)
return 0;
}
+
+#if defined(__APPLE__)
+void
+sul_release_wakelock_cb(lws_sorted_usec_list_t *sul)
+{
+ lwsl_notice("%s: releasing wakelock (pid %d)\n", __func__, (int)builder.wakelock_pid);
+ if (builder.wakelock_pid) {
+ kill(builder.wakelock_pid, SIGTERM);
+ waitpid(builder.wakelock_pid, NULL, 0);
+ builder.wakelock_pid = 0;
+ }
+}
+#endif
diff --git a/src/builder/b-private.h b/src/builder/b-private.h
index b02aa51..dec7b4e 100644
--- a/src/builder/b-private.h
+++ b/src/builder/b-private.h
@@ -104,6 +104,11 @@ struct sai_builder {
lws_sorted_usec_list_t sul_stay;
lws_sorted_usec_list_t sul_cleanup_jobs;
+#if defined(__APPLE__)
+ lws_sorted_usec_list_t sul_release_wakelock;
+ pid_t wakelock_pid;
+#endif
+
const char *metrics_uri;
const char *metrics_path;
const char *metrics_secret;
@@ -146,8 +151,10 @@ struct sai_builder {
#if !defined(WIN32)
int pipe_master_wr;
+ int pipe_suspender_wr;
#else
void *pipe_master_wr_win;
+ void *pipe_suspender_wr;
#endif
};
@@ -270,3 +277,18 @@ saib_srv_queue_json_fragments_helper(struct lws_ss_handle *h,
int
saib_queue_task_status_update(sai_plat_t *sp, struct sai_plat_server *spm,
const char *rej_task_uuid, unsigned int reason);
+
+
+extern int
+saib_suspender_fork(const char *path);
+extern int
+sai_deletion_worker(const char *home_dir);
+extern int
+saib_suspender_start(void);
+extern int
+saib_power_init(void);
+extern int
+saib_deletion_init(const char *argv0);
+extern void
+suspender_destroy(void);
+
diff --git a/src/builder/b-sai.c b/src/builder/b-sai.c
index 17d0e7d..bb08103 100644
--- a/src/builder/b-sai.c
+++ b/src/builder/b-sai.c
@@ -89,7 +89,7 @@ struct active_job_uuid {
char uuid[65];
};
-static const char *config_dir = "/etc/sai/builder";
+static const char *config_dir = "/etc/sai/builder", *argv0;
static int interrupted;
static lws_state_notify_link_t nl;
@@ -98,17 +98,6 @@ struct sai_builder builder;
extern struct lws_spawn_piped *lsp_suspender;
extern struct lws_protocols protocol_stdxxx;
extern struct lws_protocols protocol_suspender_stdxxx;
-
-extern int
-saib_suspender_fork(const char *path);
-extern int
-sai_deletion_worker(const char *home_dir);
-extern int
-saib_suspender_start(void);
-extern int
-saib_power_init(void);
-extern int
-saib_deletion_init(const char *argv0);
static const char * const default_ss_policy =
"{"
@@ -327,6 +316,12 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link,
if (current != LWS_SYSTATE_OPERATIONAL)
break;
+ if (saib_deletion_init(argv0))
+ return 1;
+
+ if (saib_suspender_fork(argv0))
+ return 1;
+
/*
* The builder JSON conf listed servers we want to connect to,
* let's collect the config, make a ss for each and add the
@@ -423,6 +418,8 @@ int main(int argc, const char **argv)
struct stat sb;
const char *p;
+ argv0 = argv[0];
+
if ((p = lws_cmdline_option(argc, argv, "--home")))
/*
* This is the deletion worker process being spawned, it only
@@ -430,11 +427,14 @@ int main(int argc, const char **argv)
*/
return sai_deletion_worker(p);
- if ((p = lws_cmdline_option(argc, argv, "-s")))
+ if ((p = lws_cmdline_option(argc, argv, "-s"))) {
+ lwsl_notice("%s: starting shutdown worker\n", __func__);
+ sleep(3000);
/*
* This is the suspend / shutdown worker process being spawned
*/
return saib_suspender_start();
+ }
if ((p = lws_cmdline_option(argc, argv, "-d")))
logs = atoi(p);
@@ -591,26 +591,12 @@ int main(int argc, const char **argv)
}
saib_power_init();
- if (saib_deletion_init(argv[0]))
- goto bail;
-
- if (saib_suspender_fork(argv[0]))
- goto bail;
while (!lws_service(builder.context, 0) && !interrupted)
;
bail:
-
- if (lsp_suspender) {
- uint8_t te = 2;
-
- /*
- * Clean up after the suspend process
- */
-
- write(lws_spawn_get_fd_stdxxx(lsp_suspender, 0), &te, 1);
- }
+ suspender_destroy();
/* destroy the unique servers */
diff --git a/src/builder/b-suspender.c b/src/builder/b-suspender.c
index eb9dce7..16375c7 100644
--- a/src/builder/b-suspender.c
+++ b/src/builder/b-suspender.c
@@ -24,6 +24,7 @@
#include <signal.h>
#include <limits.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <sys/types.h>
#if !defined(WIN32)
@@ -107,17 +108,34 @@ callback_sai_suspender_stdwsi(struct lws *wsi, enum lws_callback_reasons reason,
struct lws_protocols protocol_suspender_stdxxx =
{ "sai-suspender-stdxxx", callback_sai_suspender_stdwsi, 0, 0 };
+#if !defined(__APPLE__)
+static void reap(void *opaque, const lws_spawn_resource_us_t *res,
+ siginfo_t *si, int we_killed_him)
+{
+ lwsl_err("%s: reaped suspender fork... %d\n", __func__, si->si_status);
+}
+#endif
int
saib_suspender_fork(const char *path)
{
-#if !defined(WIN32)
+#if defined(__linux__)
struct lws_spawn_piped_info info;
- char rpath[PATH_MAX];
const char * const ea[] = { rpath, "-s", NULL };
+#endif
+ char rpath[PATH_MAX];
+
+ if (!realpath(path, rpath)) {
+ lwsl_err("%s: failed to get realpath for %s: %s\n", __func__,
+ path, strerror(errno));
+ return 1;
+ }
+
+ lwsl_err("%s: starting %s\n", __func__, rpath);
realpath(path, rpath);
+#if defined(__linux__)
memset(&info, 0, sizeof(info));
memset(&builder.suspend_nspawn, 0, sizeof(builder.suspend_nspawn));
@@ -127,12 +145,49 @@ saib_suspender_fork(const char *path)
info.opaque = (void *)&builder.suspend_nspawn;
info.protocol_name = "sai-suspender-stdxxx";
info.plsp = &lsp_suspender;
+ info.reap_cb = reap;
lsp_suspender = lws_spawn_piped(&info);
if (!lsp_suspender) {
lwsl_err("%s: suspend spawn failed\n", __func__);
return 1;
}
+#endif
+#if defined(__APPLE__)
+ {
+ int pfd[2];
+ pid_t pid;
+
+ if (pipe(pfd) == -1) {
+ lwsl_err("pipe() failed\n");
+ return 1;
+ }
+
+ fcntl(pfd[0], F_SETFD, FD_CLOEXEC);
+ fcntl(pfd[1], F_SETFD, FD_CLOEXEC);
+
+ pid = fork();
+ if (pid == -1) {
+ lwsl_err("fork() failed\n");
+ return 1;
+ }
+
+ if (!pid) {
+ close(pfd[1]); /* wr */
+ if (dup2(pfd[0], 0) < 0)
+ return 1;
+ close(pfd[0]);
+
+ execlp(rpath, rpath, "-s", (char *)NULL);
+ lwsl_err("execlp failed\n");
+ return 1;
+ }
+
+ /* parent */
+ close(pfd[0]); /* rd */
+ builder.pipe_suspender_wr = pfd[1];
+ }
+#endif
/*
* We start off idle, with no tasks on any platform and doing
@@ -142,7 +197,8 @@ saib_suspender_fork(const char *path)
lws_sul_schedule(builder.context, 0, &builder.sul_idle,
sul_idle_cb, SAI_IDLE_GRACE_US);
-#endif
+
+ lwsl_err("%s: done\n", __func__);
return 0;
}
@@ -251,3 +307,23 @@ saib_suspender_start(void)
return 0;
}
+
+void
+suspender_destroy()
+{
+#if defined(__linux__)
+ int fd = lws_spawn_get_fd_stdxxx(lsp_suspender, 0);
+#endif
+#if defined(__APPLE__)
+ int fd = builder.pipe_suspender_wr;
+#endif
+ if (lsp_suspender) {
+ uint8_t te = 2;
+
+ /*
+ * Clean up after the suspend process
+ */
+
+ write(fd, &te, 1);
+ }
+}
diff --git a/src/builder/b-task.c b/src/builder/b-task.c
index e72bab5..ced00e9 100644
--- a/src/builder/b-task.c
+++ b/src/builder/b-task.c
@@ -26,6 +26,12 @@
#include <assert.h>
#include <fcntl.h>
+#if defined(__APPLE__)
+#include <sys/wait.h>
+void
+sul_release_wakelock_cb(lws_sorted_usec_list_t *sul);
+#endif
+
#include "b-private.h"
const char *git_helper_sh =
@@ -372,10 +378,19 @@ saib_task_destroy(struct sai_nspawn *ns)
* Schedule informing all the servers we're connected to
*/
- if (!m)
+ if (!m) {
+#if defined(__APPLE__)
+ lwsl_notice("%s: last task finished, scheduling wakelock release\n", __func__);
+ lws_sul_schedule(builder.context, 0,
+ &builder.sul_release_wakelock,
+ sul_release_wakelock_cb,
+ 30 * LWS_US_PER_SEC);
+#else
lws_sul_schedule(builder.context, 0,
&builder.sul_idle, sul_idle_cb,
SAI_IDLE_GRACE_US);
+#endif
+ }
}
if (ns->task && ns->task->ac_task_container) {
@@ -1069,6 +1084,28 @@ saib_ws_json_rx_builder(struct sai_plat_server *spm, const void *in, size_t len)
if (saib_queue_task_status_update(sp, spm, task->uuid, SAI_TASK_REASON_ACCEPTED))
goto bail;
+#if defined(__APPLE__)
+ /*
+ * If we started the first task, acquire a wakelock to prevent
+ * idle suspend
+ */
+ if (sp->nspawn_owner.count == 1 && !builder.wakelock_pid) {
+ pid_t pid = fork();
+
+ if (pid == -1)
+ lwsl_err("%s: fork for wakelock failed\n", __func__);
+ else if (!pid) {
+ execl("/usr/bin/caffeinate", "/usr/bin/caffeinate", "-i", (char *)NULL);
+ exit(1); /* should not get here */
+ } else {
+ lwsl_notice("%s: acquired wakelock (pid %d)\n", __func__, (int)pid);
+ builder.wakelock_pid = pid;
+ }
+ }
+ /* if there's a pending wakelock release, cancel it */
+ lws_sul_cancel(&builder.sul_release_wakelock);
+#endif
+
break;
case SAIB_RX_TASK_CANCEL: