Permalink
Browse files

log messages sent to stdout/stderr before the VM is booted

Change-Id: I604135c8ccd414cbd0500254a0500182a58259c4
Reviewed-on: http://review.couchbase.org/10702
Tested-by: Marty Schoch <marty.schoch@gmail.com>
Reviewed-by: Marty Schoch <marty.schoch@gmail.com>
  • Loading branch information...
1 parent bcae862 commit 53c57cb0e2cf4b5f22977ceaf7d7f8c701bd6003 @mschoch mschoch committed Nov 8, 2011
Showing with 163 additions and 0 deletions.
  1. +106 −0 jni/com_couchbase_android_ErlangThread.cpp
  2. +57 −0 jni/erl_printf.h
@@ -6,10 +6,89 @@
#include "android/log.h"
+#include "erl_printf.h"
+
#define LOG_TAG "ErlangThread"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define ALLOC(X) malloc(X)
+#define REALLOC(X,Y) realloc(X,Y)
+#define FREE(X) free(X)
+
+#define ANDROID_VPRINTF_BUF_INC_SIZE 1024
+
+int (*ref_erts_vdsprintf)(erts_dsprintf_buf_t *dsbufp, const char *format, va_list arglist) = NULL;
+
+static erts_dsprintf_buf_t * grow_android_vprintf_buf(erts_dsprintf_buf_t *dsbufp, size_t need)
+{
+ char *buf;
+ size_t size;
+
+ if (!dsbufp->str) {
+ size = (((need + ANDROID_VPRINTF_BUF_INC_SIZE - 1)
+ / ANDROID_VPRINTF_BUF_INC_SIZE)
+ * ANDROID_VPRINTF_BUF_INC_SIZE);
+ buf = (char *) ALLOC(size * sizeof(char));
+ }
+ else {
+ size_t free_size = dsbufp->size - dsbufp->str_len;
+
+ if (need <= free_size)
+ return dsbufp;
+
+ size = need - free_size + ANDROID_VPRINTF_BUF_INC_SIZE;
+ size = (((size + ANDROID_VPRINTF_BUF_INC_SIZE - 1)
+ / ANDROID_VPRINTF_BUF_INC_SIZE)
+ * ANDROID_VPRINTF_BUF_INC_SIZE);
+ size += dsbufp->size;
+ buf = (char *) REALLOC((void *) dsbufp->str,
+ size * sizeof(char));
+ }
+ if (!buf)
+ return NULL;
+ if (buf != dsbufp->str)
+ dsbufp->str = buf;
+ dsbufp->size = size;
+ return dsbufp;
+}
+
+static int android_stdout_vprintf(char *format, va_list arg_list) {
+ int res,i;
+ erts_dsprintf_buf_t dsbuf = ERTS_DSPRINTF_BUF_INITER(grow_android_vprintf_buf);
+ res = ref_erts_vdsprintf(&dsbuf, format, arg_list);
+ if (res >= 0) {
+ char *tmp = (char*)ALLOC((dsbuf.str_len + 1)*sizeof(char));
+ for (i=0;i<dsbuf.str_len;++i) {
+ tmp[i] = dsbuf.str[i];
+ }
+ tmp[dsbuf.str_len] = NULL;
+ LOGV(tmp);
+ FREE(tmp);
+ }
+ if (dsbuf.str)
+ FREE((void *) dsbuf.str);
+ return res;
+}
+
+static int android_stderr_vprintf(char *format, va_list arg_list) {
+ int res,i;
+ erts_dsprintf_buf_t dsbuf = ERTS_DSPRINTF_BUF_INITER(grow_android_vprintf_buf);
+ res = ref_erts_vdsprintf(&dsbuf, format, arg_list);
+ if (res >= 0) {
+ char *tmp = (char*)ALLOC((dsbuf.str_len + 1)*sizeof(char));
+ for (i=0;i<dsbuf.str_len;++i) {
+ tmp[i] = dsbuf.str[i];
+ }
+ tmp[dsbuf.str_len] = NULL;
+ LOGE(tmp);
+ FREE(tmp);
+ }
+ if (dsbuf.str)
+ FREE((void *) dsbuf.str);
+ return res;
+}
+
JavaVM *jvm;
jclass ErlangThread;
jmethodID ErlMessageMethod;
@@ -20,6 +99,8 @@ JNIEXPORT void JNICALL Java_com_couchbase_android_ErlangThread_start_1erlang
int i, argc;
char ** argv;
void (*erl_start)(int, char**) = NULL;
+ int (**erts_printf_stdout_func)(char *, va_list) = NULL;
+ int (**erts_printf_stderr_func)(char *, va_list) = NULL;
const char *sopath = env->GetStringUTFChars(j_sopath, &iscopy);
const char *bindir = env->GetStringUTFChars(j_bindir, &iscopy);
@@ -35,6 +116,31 @@ JNIEXPORT void JNICALL Java_com_couchbase_android_ErlangThread_start_1erlang
LOGE("Failed to find erl_start: %s", dlerror());
goto cleanup;
}
+
+ *(void **)(&erts_printf_stdout_func) = dlsym(handle, "erts_printf_stdout_func");
+ if(!erts_printf_stdout_func) {
+ LOGE("Failed to find erts_printf_stdout_func: %s", dlerror());
+ goto cleanup;
+ }
+ else {
+ *erts_printf_stdout_func = android_stdout_vprintf;
+ }
+
+ *(void **)(&erts_printf_stderr_func) = dlsym(handle, "erts_printf_stderr_func");
+ if(!erts_printf_stderr_func) {
+ LOGE("Failed to find erts_printf_stderr_func: %s", dlerror());
+ goto cleanup;
+ }
+ else {
+ *erts_printf_stderr_func = android_stderr_vprintf;
+ }
+
+ *(void **)(&ref_erts_vdsprintf) = dlsym(handle, "erts_vdsprintf");
+ if(!erts_vdsprintf) {
+ LOGE("Failed to find erts_vdsprintf: %s", dlerror());
+ goto cleanup;
+ }
+
argc = env->GetArrayLength(j_args);
argv = (char**) malloc(sizeof(char*) * argc);
View
@@ -0,0 +1,57 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef ERL_PRINTF_H_
+#define ERL_PRINTF_H_
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int (*erts_printf_stdout_func)(char *, va_list);
+extern int (*erts_printf_stderr_func)(char *, va_list);
+extern int erts_printf_add_cr_to_stdout;
+extern int erts_printf_add_cr_to_stderr;
+extern int (*erts_printf_block_fpe)(void);
+extern void (*erts_printf_unblock_fpe)(int);
+
+typedef struct erts_dsprintf_buf_t_ erts_dsprintf_buf_t;
+
+struct erts_dsprintf_buf_t_ {
+ char *str;
+ size_t str_len;
+ size_t size;
+ erts_dsprintf_buf_t *(*grow)(erts_dsprintf_buf_t *, size_t);
+};
+
+#define ERTS_DSPRINTF_BUF_INITER(GFUNC) {NULL, 0, 0, (GFUNC)}
+
+int erts_printf(const char *, ...);
+int erts_fprintf(FILE *, const char *, ...);
+int erts_fdprintf(int, const char *, ...);
+int erts_sprintf(char *, const char *, ...);
+int erts_snprintf(char *, size_t, const char *, ...);
+int erts_dsprintf(erts_dsprintf_buf_t *, const char *, ...);
+
+int erts_vprintf(const char *, va_list);
+int erts_vfprintf(FILE *, const char *, va_list);
+int erts_vfdprintf(int, const char *, va_list);
+int erts_vsprintf(char *, const char *, va_list);
+int erts_vsnprintf(char *, size_t, const char *, va_list);
+int erts_vdsprintf(erts_dsprintf_buf_t *, const char *, va_list);
+
+#endif /* #ifndef ERL_PRINTF_H_ */

0 comments on commit 53c57cb

Please sign in to comment.