Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
log messages sent to stdout/stderr before the VM is booted
Browse files Browse the repository at this point in the history
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
mschoch committed Nov 9, 2011
1 parent bcae862 commit 53c57cb
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 0 deletions.
106 changes: 106 additions & 0 deletions jni/com_couchbase_android_ErlangThread.cpp
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);

Expand Down
57 changes: 57 additions & 0 deletions jni/erl_printf.h
@@ -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.