Never call at_exit functions from android dalvik vm

This commit is contained in:
Jeremy Lakeman 2014-09-08 11:24:05 +09:30
parent 097f72f04f
commit 83949f6585
3 changed files with 69 additions and 38 deletions

View File

@ -39,22 +39,26 @@ SERVALD_LOCAL_LDLIBS = -L$(SYSROOT)/usr/lib -llog
# Build libserval.so
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(NACL_SOURCES) $(SERVALD_SRC_FILES) version_servald.c
LOCAL_SRC_FILES := $(NACL_SOURCES) $(SERVALD_SRC_FILES) version_servald.c android.c
LOCAL_CFLAGS += $(SERVALD_LOCAL_CFLAGS)
LOCAL_LDLIBS := $(SERVALD_LOCAL_LDLIBS)
LOCAL_MODULE := serval
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= servalwrap.c
LOCAL_MODULE:= servald
include $(BUILD_EXECUTABLE)
ifdef SERVALD_WRAP
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= servalwrap.c
LOCAL_MODULE:= servald
include $(BUILD_EXECUTABLE)
endif
# Build servald for use with gdb
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= $(NACL_SOURCES) $(SERVALD_SRC_FILES) version_servald.c
LOCAL_CFLAGS += $(SERVALD_LOCAL_CFLAGS)
LOCAL_LDLIBS := $(SERVALD_LOCAL_LDLIBS)
LOCAL_STATIC_LIBRARIES := $(SERVALD_LOCAL_STATIC_LIBRARIES)
LOCAL_MODULE:= servaldsimple
include $(BUILD_EXECUTABLE)
ifdef SERVALD_SIMPLE
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= $(NACL_SOURCES) $(SERVALD_SRC_FILES) version_servald.c
LOCAL_CFLAGS += $(SERVALD_LOCAL_CFLAGS)
LOCAL_LDLIBS := $(SERVALD_LOCAL_LDLIBS)
LOCAL_STATIC_LIBRARIES := $(SERVALD_LOCAL_STATIC_LIBRARIES)
LOCAL_MODULE:= servaldsimple
include $(BUILD_EXECUTABLE)
endif

31
android.c Normal file
View File

@ -0,0 +1,31 @@
/*
Copyright (C) 2014 Serval Project Inc.
Android specific functions that we don't need on other platforms
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include "log.h"
#include "conf.h"
// We don't want to call any at_exit functions from the dalvik VM
void _exit(int status);
void exit(int status)
{
if (config.debug.verbose)
DEBUGF("Calling _exit(%d)", status);
_exit(status);
}

View File

@ -502,10 +502,6 @@ static int app_server_start(const struct cli_parsed *parsed, struct cli_context
if (cli_arg(parsed, "exec", &execpath, cli_absolute_path, NULL) == -1)
RETURN(-1);
int foregroundP = cli_arg(parsed, "foreground", NULL, NULL, NULL) == 0;
#ifdef HAVE_JNI_H
if (context && context->jni_env && execpath == NULL)
RETURN(WHY("Must supply \"exec <path>\" arguments when invoked via JNI"));
#endif
/* Create the instance directory if it does not yet exist */
if (create_serval_instance_dir() == -1)
RETURN(-1);
@ -558,11 +554,8 @@ static int app_server_start(const struct cli_parsed *parsed, struct cli_context
_exit() is used on non-Android systems, then source code coverage does not get reported,
because it relies on an atexit() callback to write the accumulated counters into .gcda
files. */
#ifdef ANDROID
# define EXIT_CHILD(n) _exit(n)
#else
# define EXIT_CHILD(n) exit(n)
#endif
if (config.debug.verbose)
DEBUG("Child Process");
// Ensure that all stdio streams are flushed before forking, so that if a child calls
// exit(), it will not result in any buffered output being written twice to the file
// descriptor.
@ -570,7 +563,7 @@ static int app_server_start(const struct cli_parsed *parsed, struct cli_context
fflush(stderr);
switch (fork()) {
case -1:
EXIT_CHILD(WHY_perror("fork"));
exit(WHY_perror("fork"));
case 0: {
/* Grandchild process. Close logfile (so that it gets re-opened again on demand, with
our own file pointer), disable logging to stderr (about to get redirected to
@ -578,21 +571,23 @@ static int app_server_start(const struct cli_parsed *parsed, struct cli_context
start a new process session so that if we are being started by an adb shell session
on an Android device, then we don't receive a SIGHUP when the adb shell process ends.
*/
if (config.debug.verbose)
DEBUG("Grand-Child Process, reopening log");
close_log_file();
disable_log_stderr();
int fd;
if ((fd = open("/dev/null", O_RDWR, 0)) == -1)
EXIT_CHILD(WHY_perror("open(\"/dev/null\")"));
exit(WHY_perror("open(\"/dev/null\")"));
if (setsid() == -1)
EXIT_CHILD(WHY_perror("setsid"));
exit(WHY_perror("setsid"));
if (chdir(dir) == -1)
EXIT_CHILD(WHYF_perror("chdir(%s)", alloca_str_toprint(dir)));
if (dup2(fd, 0) == -1)
EXIT_CHILD(WHYF_perror("dup2(%d,0)", fd));
if (dup2(fd, 1) == -1)
EXIT_CHILD(WHYF_perror("dup2(%d,1)", fd));
if (dup2(fd, 2) == -1)
EXIT_CHILD(WHYF_perror("dup2(%d,2)", fd));
exit(WHYF_perror("chdir(%s)", alloca_str_toprint(dir)));
if (dup2(fd, STDIN_FILENO) == -1)
exit(WHYF_perror("dup2(%d,stdin)", fd));
if (dup2(fd, STDOUT_FILENO) == -1)
exit(WHYF_perror("dup2(%d,stdout)", fd));
if (dup2(fd, STDERR_FILENO) == -1)
exit(WHYF_perror("dup2(%d,stderr)", fd));
if (fd > 2)
(void)close(fd);
/* The execpath option is provided so that a JNI call to "start" can be made which
@ -601,17 +596,18 @@ static int app_server_start(const struct cli_parsed *parsed, struct cli_context
if (execpath) {
/* Need the cast on Solaris because it defines NULL as 0L and gcc doesn't see it as a
sentinal. */
execl(execpath, execpath, "start", "foreground", (void *)NULL);
WHYF_perror("execl(%s,\"start\",\"foreground\")", alloca_str_toprint(execpath));
EXIT_CHILD(-1);
if (config.debug.verbose)
DEBUGF("Calling execl %s start foreground", execpath);
execl(execpath, "servald", "start", "foreground", (void *)NULL);
WHYF_perror("execl(%s, \"servald\", \"start\", \"foreground\")", alloca_str_toprint(execpath));
exit(-1);
}
EXIT_CHILD(server());
// NOT REACHED
exit(server());
// UNREACHABLE
}
}
// TODO wait for server_write_pid() to signal more directly?
EXIT_CHILD(0); // Main process is waitpid()-ing for this.
#undef EXIT_CHILD
exit(0); // Main process is waitpid()-ing for this.
}
}
/* Main process. Wait for the child process to fork the grandchild and exit. */