Skip to content

Commit 6c44b0e

Browse files
committed
feat: Spawn process via posix_spawn
1 parent 524d8ae commit 6c44b0e

File tree

2 files changed

+112
-20
lines changed

2 files changed

+112
-20
lines changed

service/src/main.c

Lines changed: 108 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#define _GNU_SOURCE
12
#include <stdlib.h>
23
#include <string.h>
34
#include <stdio.h>
4-
#include <unistd.h>
5-
#include <glib.h>
5+
#include <spawn.h>
6+
#include <sys/types.h>
7+
#include <sys/wait.h>
8+
#include <signal.h>
69
#include <glib-object.h>
710
#include <luna-service2/lunaservice.h>
811
#include <pbnjson.h>
@@ -32,49 +35,128 @@ char *hyperiond_cmdline(char *args)
3235
return tmp;
3336
}
3437

35-
char *hyperiond_start_cmdline()
38+
int daemon_start(pid_t *pid)
3639
{
37-
// Run hyperiond in background
38-
return hyperiond_cmdline("&");
40+
int res = 0;
41+
42+
char *env_library_path;
43+
char *env_armcap;
44+
char *application_executable_path;
45+
46+
asprintf(&env_library_path, "LD_LIBRARY_PATH=%s", HYPERION_PATH);
47+
asprintf(&env_armcap, "OPENSSL_armcap=%d", 0);
48+
asprintf(&application_executable_path, "%s/hyperiond", HYPERION_PATH);
49+
50+
char *env_vars[] = {env_library_path, env_armcap, NULL};
51+
char *argv[] = {application_executable_path};
52+
53+
res = posix_spawn(pid, application_executable_path, NULL, NULL, argv, env_vars);
54+
DBG("posix_spawn: pid=%d, application_path=%s, env={%s,%s}",
55+
*pid, application_executable_path, env_library_path, env_armcap);
56+
57+
free(env_library_path);
58+
free(env_armcap);
59+
free(application_executable_path);
60+
61+
return res;
62+
}
63+
64+
void *execution_task(void *data)
65+
{
66+
int res = 0;
67+
int status = 0;
68+
69+
service_t *service = (service_t *)data;
70+
71+
do {
72+
if (service->daemon_pid <= 0) {
73+
WARN("Invalid daemon PID: %d - exiting execution loop");
74+
break;
75+
}
76+
res = waitpid(service->daemon_pid, &status, WNOHANG);
77+
DBG("waitpid: pid=%d, status=%d, res=%d", service->daemon_pid, status, res);
78+
79+
if (res == -1) {
80+
ERR("waitpid: res=%d", res);
81+
break;
82+
}
83+
84+
if (WIFEXITED(status)) {
85+
INFO("Child status: exited, status=%d\n", WEXITSTATUS(status));
86+
} else if (WIFSIGNALED(status)) {
87+
INFO("Child status: killed by signal %d\n", WTERMSIG(status));
88+
} else if (WIFSTOPPED(status)) {
89+
INFO("Child status: stopped by signal %d\n", WSTOPSIG(status));
90+
} else if (WIFCONTINUED(status)) {
91+
INFO("Child status: continued\n");
92+
}
93+
94+
usleep(200 * 1000); // 200ms
95+
96+
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
97+
98+
service->daemon_pid = 0;
99+
return NULL;
39100
}
40101

41102
char *hyperiond_version_cmdline()
42103
{
43104
return hyperiond_cmdline("--version");
44105
}
45106

107+
bool is_running(pid_t pid)
108+
{
109+
return (pid > 0);
110+
}
111+
46112
int hyperiond_start(service_t* service)
47113
{
114+
int res = 0;
48115
if (!is_elevated()) {
49116
return 1;
50-
} else if (service->running) {
117+
} else if (is_running(service->daemon_pid)) {
51118
return 2;
52119
}
53120

54-
service->running = true;
55-
// TODO: system() ftw
56-
char *command = hyperiond_start_cmdline();
57-
int res = system(command);
121+
res = daemon_start(&service->daemon_pid);
122+
DBG("hyperiond_start: daemon_start -> PID=%d", service->daemon_pid);
58123

59124
if (res != 0) {
60-
service->running = false;
125+
ERR("hyperiond_start: Failed daemon_start with res=%d", res);
61126
return 3;
62127
}
63128

129+
res = pthread_create(&service->execution_thread, NULL, execution_task, service);
130+
if (res != 0) {
131+
ERR("hyperiond_start: pthread_create failed, res=%d", res);
132+
return 4;
133+
}
134+
64135
return 0;
65136
}
66137

67138
int hyperiond_stop(service_t* service)
68139
{
140+
int res = 0;
141+
69142
if (!is_elevated()) {
70143
return 1;
71-
} else if (!service->running) {
144+
} else if (!is_running(service->daemon_pid)) {
72145
return 2;
73146
}
74147

75-
// TODO: system() ftw
76-
system("killall -9 hyperiond");
77-
service->running = false;
148+
res = kill(service->daemon_pid, SIGTERM);
149+
if (res != 0) {
150+
ERR("hyperiond_stop: kill failed, res=%d", res);
151+
return 3;
152+
}
153+
154+
res = pthread_join(service->execution_thread, NULL);
155+
if (res != 0) {
156+
ERR("hyperiond_stop: pthread_join failed, res=%d", res);
157+
return 4;
158+
}
159+
service->execution_thread = NULL;
78160

79161
return 0;
80162
}
@@ -131,8 +213,13 @@ bool service_method_start(LSHandle* sh, LSMessage* msg, void* data)
131213
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG was already running"));
132214
break;
133215
case 3:
134-
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG failed to start, reason: Unknown"));
216+
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG failed to start, posix_spawn failed"));
217+
break;
218+
case 4:
219+
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG failed to start, pthread_create failed"));
135220
break;
221+
default:
222+
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG failed to start, reason: Unknown"));
136223
}
137224
LSMessageReply(sh, msg, jvalue_tostring_simple(jobj), &lserror);
138225

@@ -160,6 +247,8 @@ bool service_method_stop(LSHandle* sh, LSMessage* msg, void* data)
160247
case 2:
161248
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG was not running"));
162249
break;
250+
default:
251+
jobject_set(jobj, j_cstr_to_buffer("status"), jstring_create("Hyperion.NG failed to stop, reason: Unknown"));
163252
}
164253
LSMessageReply(sh, msg, jvalue_tostring_simple(jobj), &lserror);
165254

@@ -201,7 +290,7 @@ bool service_method_status(LSHandle* sh, LSMessage* msg, void* data)
201290

202291
jvalue_ref jobj = jobject_create();
203292
jobject_set(jobj, j_cstr_to_buffer("returnValue"), jboolean_create(true));
204-
jobject_set(jobj, j_cstr_to_buffer("running"), jboolean_create(service->running));
293+
jobject_set(jobj, j_cstr_to_buffer("running"), jboolean_create(is_running(service->daemon_pid)));
205294
jobject_set(jobj, j_cstr_to_buffer("elevated"), jboolean_create(is_elevated()));
206295

207296
LSMessageReply(sh, msg, jvalue_tostring_simple(jobj), &lserror);
@@ -240,11 +329,11 @@ LSMethod methods[] = {
240329

241330
int main()
242331
{
243-
service_t service;
332+
service_t service = {0};
244333
LSHandle *handle = NULL;
245334
LSError lserror;
246335

247-
service.running = FALSE;
336+
service.daemon_pid = 0;
248337
service.hyperiond_version = NULL;
249338

250339
LSErrorInit(&lserror);

service/src/service.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#pragma once
22

3+
#include <unistd.h>
34
#include <glib.h>
5+
#include <pthread.h>
46

57
#define SERVICE_NAME "org.webosbrew.hyperion.ng.loader.service"
68
#define HYPERION_PATH "/media/developer/apps/usr/palm/services/org.webosbrew.hyperion.ng.loader.service/hyperion"
79

810
typedef struct {
9-
bool running;
1011
char *hyperiond_version;
12+
pid_t daemon_pid;
13+
pthread_t execution_thread;
1114
} service_t;
1215

1316
int service_start(service_t* service);

0 commit comments

Comments
 (0)