diff options
| author | 2024-01-11 23:07:18 -0600 | |
|---|---|---|
| committer | 2024-01-11 23:07:18 -0600 | |
| commit | 8667391ffee160409cfb857e7bba5e2df58ecb06 (patch) | |
| tree | 87fb302520451f8d3da276d12965ff17700496e9 /src/launch.c | |
| parent | oops forgot to update profile (diff) | |
add detach stuff
Diffstat (limited to 'src/launch.c')
| -rw-r--r-- | src/launch.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/launch.c b/src/launch.c index 942cbbb..12246de 100644 --- a/src/launch.c +++ b/src/launch.c @@ -14,6 +14,8 @@ #include <stdarg.h> #include <stdio.h> #include <unistd.h> +#include <signal.h> +#include <sys/wait.h> bool l2_launch__check_feature(const char *name, json_t *val, void *user); int l2_launch_init_substitutor(struct l2_launch *launch); @@ -573,6 +575,84 @@ int l2_launch__find_jni(struct l2_launch *launch, char **jnifile) return 0; } +volatile bool l2_launch__signal_wait = true; +pid_t l2_launch__wait_pid = 0; + +void l2_launch__handle_sigusr1(int signum, siginfo_t *info, void *unk) +{ + L2_UNUSED(unk); + + if (signum == SIGUSR1 && info->si_pid == l2_launch__wait_pid) + l2_launch__signal_wait = false; +} + +int l2_launch__detach(void) +{ + pid_t childpid; + + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_sigaction = &l2_launch__handle_sigusr1; + act.sa_flags = SA_SIGINFO | SA_RESETHAND; + + if (sigaction(SIGUSR1, &act, NULL) < 0) { + CMD_ERROR("Failed to set signal action for SIGUSR1: %s", strerror(errno)); + return -1; + } + + if ((childpid = fork()) < 0) { + CMD_ERROR("Failed to fork(): %s", strerror(errno)); + return -1; + } else if (!childpid) { + raise(SIGUSR1); /* clear signal handler */ + return 0; + } else { + l2_launch__wait_pid = childpid; + + int waitres = 0; + pid_t pidret; + while (l2_launch__signal_wait) { + if ((pidret = waitpid(childpid, &waitres, WNOHANG)) < 0) { + CMD_ERROR("Failed to wait for child %d: %s", childpid, strerror(errno)); + return -1; + } + + if (pidret == childpid && WIFEXITED(waitres)) { + CMD_ERROR("Child exited prematurely (%d)", WEXITSTATUS(waitres)); + return -1; + } + + pause(); + } + + CMD_INFO0("Game launched! Exiting."); + fflush(stderr); + + _exit(0); + } +} + +int l2_launch__detach_complete(void) +{ + pid_t parent = getppid(); + + if (setsid() == (pid_t)-1) { + CMD_ERROR("Failed to set SID: %s", strerror(errno)); + return -1; + } + + if (kill(parent, SIGUSR1) < 0) { + CMD_ERROR("Failed to kill parent (%d): %s", parent, strerror(errno)); + return -1; + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + return 0; +} + int l2_launch_jni(struct l2_launch *launch) { int res = 0; @@ -602,6 +682,8 @@ int l2_launch_jni(struct l2_launch *launch) memset(&args, 0, sizeof(JavaVMInitArgs)); args.version = JNI_VERSION_1_8; + if (launch->detach && l2_launch__detach() < 0) return -1; + char *main_class_fq; size_t main_class_len; L2_ASTRDUP(main_class_fq, main_class_len, launch->main_class); @@ -660,6 +742,11 @@ int l2_launch_jni(struct l2_launch *launch) goto cleanup; } + if (launch->detach && l2_launch__detach_complete() < 0) { + res = -1; + goto cleanup; + } + (*env)->CallStaticVoidMethod(env, jmaincls, main_method, jargs); if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); |
