mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-19 15:05:36 +02:00
Bug 521788 - spawner doesnt kill child process on MacOS X
Fixed by copying code from org.eclipse.cdt.core.linux that contains the fix from bug 119387 : set the process group by calling setpgid() when forking a process, and use killpg() for killing the entire process group on termination. This also aligns MacOS code fully with Linux code. Tested on MacOSX 10.8 and 10.13 beta. Binaries will be submitted with the related fix for bug 519886. Change-Id: I87df87caa88cff60b4d9eee2252252234d1a4f84 Signed-off-by: Martin Oberhuber <mober.at+eclipse@gmail.com>
This commit is contained in:
parent
84689e06fd
commit
1019030e74
3 changed files with 97 additions and 64 deletions
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002, 2011 QNX Software Systems and others.
|
||||
* Copyright (c) 2004, 2010 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -7,7 +7,10 @@
|
|||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
* Wind River Systems, Inc.
|
||||
* Mikhail Zabaluev (Nokia) - bug 82744
|
||||
* Mikhail Sennikovsky - bug 145737
|
||||
*******************************************************************************/
|
||||
#include "exec0.h"
|
||||
#include "openpty.h"
|
||||
#include <unistd.h>
|
||||
|
@ -20,7 +23,7 @@
|
|||
#include <termios.h>
|
||||
|
||||
/* from pfind.c */
|
||||
extern char *pfind(const char *name, char *const envp[]);
|
||||
extern char *pfind(const char *name, char * const envp[]);
|
||||
|
||||
pid_t
|
||||
exec_pty(const char *path, char *const argv[], char *const envp[],
|
||||
|
@ -43,7 +46,7 @@ exec_pty(const char *path, char *const argv[], char *const envp[],
|
|||
/*
|
||||
* Make sure we can create our pipes before forking.
|
||||
*/
|
||||
if (console && channels != NULL) {
|
||||
if (channels != NULL && console) {
|
||||
if (pipe(pipe2) < 0) {
|
||||
fprintf(stderr, "%s(%d): returning due to error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
|
||||
free(full_path);
|
||||
|
@ -90,6 +93,7 @@ exec_pty(const char *path, char *const argv[], char *const envp[],
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* redirections */
|
||||
dup2(fds, STDIN_FILENO); /* dup stdin */
|
||||
dup2(fds, STDOUT_FILENO); /* dup stdout */
|
||||
|
@ -119,21 +123,19 @@ exec_pty(const char *path, char *const argv[], char *const envp[],
|
|||
_exit(127);
|
||||
|
||||
} else if (childpid != 0) { /* parent */
|
||||
|
||||
if (console) {
|
||||
set_noecho(fdm);
|
||||
}
|
||||
if (channels != NULL) {
|
||||
/* close the write end of pipe1 */
|
||||
if (console && close(pipe2[1]) == -1)
|
||||
perror("close(pipe2[1])");
|
||||
|
||||
channels[0] = fdm; /* Input Stream. */
|
||||
channels[1] = fdm; /* Output Stream. */
|
||||
if (console) { /* stderr Stream. */
|
||||
channels[2] = pipe2[0];
|
||||
if (console) {
|
||||
/* close the write end of pipe1 */
|
||||
if (close(pipe2[1]) == -1)
|
||||
perror("close(pipe2[1])");
|
||||
channels[2] = pipe2[0]; /* stderr Stream. */
|
||||
} else {
|
||||
channels[2] = fdm;
|
||||
channels[2] = fdm; /* Error Stream. */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 QNX Software Systems and others.
|
||||
* Copyright (c) 2002, 2010 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -7,6 +7,8 @@
|
|||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
* Wind River Systems, Inc.
|
||||
* Mikhail Sennikovsky - bug 145737
|
||||
*******************************************************************************/
|
||||
#include "exec0.h"
|
||||
#include <unistd.h>
|
||||
|
@ -18,7 +20,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/* from pfind.c */
|
||||
extern char *pfind(const char *name, char *const envp[]);
|
||||
extern char *pfind(const char *name, char * const envp[]);
|
||||
|
||||
pid_t
|
||||
exec0(const char *path, char *const argv[], char *const envp[],
|
||||
|
@ -90,6 +92,8 @@ exec0(const char *path, char *const argv[], char *const envp[],
|
|||
close(fd++);
|
||||
}
|
||||
|
||||
setpgid(getpid(), getpid());
|
||||
|
||||
if (envp[0] == NULL) {
|
||||
execv(full_path, argv);
|
||||
} else {
|
||||
|
@ -134,9 +138,18 @@ int wait0(pid_t pid)
|
|||
int status;
|
||||
int val = -1;
|
||||
|
||||
if (pid < 0 || waitpid(pid, &status, 0) < 0)
|
||||
if (pid < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
for (;;) {
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
if (errno == EINTR) {
|
||||
// interrupted system call - retry
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
val = WEXITSTATUS(status);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
* Wind River Systems, Inc.
|
||||
* Mikhail Zabaluev (Nokia) - bug 82744
|
||||
*******************************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -90,52 +92,53 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2
|
|||
(JNIEnv *env, jobject jobj, jobjectArray jcmd, jobjectArray jenv, jstring jdir, jintArray jchannels,
|
||||
jstring jslaveName, jint masterFD, jboolean console)
|
||||
{
|
||||
jint *channels = (*env)->GetIntArrayElements(env, jchannels, 0);
|
||||
const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL);
|
||||
const char *pts_name = (*env)->GetStringUTFChars(env, jslaveName, NULL);
|
||||
char **cmd = NULL;
|
||||
char **envp = NULL;
|
||||
int fd[3];
|
||||
pid_t pid = -1;
|
||||
|
||||
if (channels == NULL)
|
||||
goto bail_out;
|
||||
|
||||
cmd = alloc_c_array(env, jcmd);
|
||||
if (cmd == NULL)
|
||||
goto bail_out;
|
||||
|
||||
envp = alloc_c_array(env, jenv);
|
||||
if (envp == NULL)
|
||||
goto bail_out;
|
||||
|
||||
jint *channels = (*env)->GetIntArrayElements(env, jchannels, 0);
|
||||
const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL);
|
||||
const char *pts_name = (*env)->GetStringUTFChars(env, jslaveName, NULL);
|
||||
char **cmd = NULL;
|
||||
char **envp = NULL;
|
||||
int fd[3];
|
||||
pid_t pid = -1;
|
||||
|
||||
if (channels == NULL)
|
||||
goto bail_out;
|
||||
|
||||
cmd = alloc_c_array(env, jcmd);
|
||||
if (cmd == NULL)
|
||||
goto bail_out;
|
||||
|
||||
envp = alloc_c_array(env, jenv);
|
||||
if (envp == NULL)
|
||||
goto bail_out;
|
||||
|
||||
#if DEBUGIT
|
||||
fprintf(stderr, "command:");
|
||||
print_array(cmd);
|
||||
fprintf(stderr, "Envp:");
|
||||
print_array(envp);
|
||||
fprintf(stderr, "dirpath: %s\n", dirpath);
|
||||
fprintf(stderr, "pts_name: %s\n", pts_name);
|
||||
fprintf(stderr, "command:");
|
||||
print_array(cmd);
|
||||
fprintf(stderr, "Envp:");
|
||||
print_array(envp);
|
||||
fprintf(stderr, "dirpath: %s\n", dirpath);
|
||||
fprintf(stderr, "pts_name: %s\n", pts_name);
|
||||
#endif
|
||||
|
||||
pid = exec_pty(cmd[0], cmd, envp, dirpath, fd, pts_name, masterFD, console);
|
||||
if (pid < 0)
|
||||
goto bail_out;
|
||||
|
||||
channels[0] = fd[0];
|
||||
channels[1] = fd[1];
|
||||
channels[2] = fd[2];
|
||||
|
||||
bail_out:
|
||||
(*env)->ReleaseIntArrayElements(env, jchannels, channels, 0);
|
||||
(*env)->ReleaseStringUTFChars(env, jdir, dirpath);
|
||||
(*env)->ReleaseStringUTFChars(env, jslaveName, pts_name);
|
||||
if (cmd)
|
||||
free_c_array(cmd);
|
||||
if (envp)
|
||||
free_c_array(envp);
|
||||
return pid;
|
||||
|
||||
pid = exec_pty(cmd[0], cmd, envp, dirpath, fd, pts_name, masterFD, console);
|
||||
if (pid < 0)
|
||||
goto bail_out;
|
||||
|
||||
channels[0] = fd[0];
|
||||
channels[1] = fd[1];
|
||||
channels[2] = fd[2];
|
||||
|
||||
bail_out:
|
||||
(*env)->ReleaseIntArrayElements(env, jchannels, channels, 0);
|
||||
(*env)->ReleaseStringUTFChars(env, jdir, dirpath);
|
||||
(*env)->ReleaseStringUTFChars(env, jslaveName, pts_name);
|
||||
if (cmd)
|
||||
free_c_array(cmd);
|
||||
if (envp)
|
||||
free_c_array(envp);
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_eclipse_cdt_utils_spawner_Spawner_exec1(JNIEnv * env, jobject jobj,
|
||||
|
@ -246,23 +249,38 @@ Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv * env, jobject jobj,
|
|||
|
||||
switch (sig) {
|
||||
case 0: /* NOOP */
|
||||
status = kill(pid, 0);
|
||||
status = killpg(pid, 0);
|
||||
if(status == -1) {
|
||||
status = kill(pid, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* INTERRUPT */
|
||||
status = kill(pid, SIGINT);
|
||||
status = killpg(pid, SIGINT);
|
||||
if(status == -1) {
|
||||
status = kill(pid, SIGINT);
|
||||
}
|
||||
break;
|
||||
|
||||
case 9: /* KILL */
|
||||
status = kill(pid, SIGKILL);
|
||||
status = killpg(pid, SIGKILL);
|
||||
if(status == -1) {
|
||||
status = kill(pid, SIGKILL);
|
||||
}
|
||||
break;
|
||||
|
||||
case 15: /* TERM */
|
||||
status = kill(pid, SIGTERM);
|
||||
status = killpg(pid, SIGTERM);
|
||||
if(status == -1) {
|
||||
status = kill(pid, SIGTERM);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = kill(pid, sig); /* WHAT ?? */
|
||||
status = killpg(pid, sig); /* WHAT ?? */
|
||||
if(status == -1) {
|
||||
status = kill(pid, sig); /* WHAT ?? */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue