Source

ocaml-toplevel-android / jni / start.c

Diff from to

jni/start.c

 #include <sys/socket.h>
 #include <sys/un.h>
 
-#define SERVER     "jp.co.itpl.ocamltop.stdinout"
-#define SERVER_ERR "jp.co.itpl.ocamltop.stderr"
+#include <android/log.h>
+
+#define LOG_TAG "ocaml-android"
+#define LOGD(...) do { __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); } while(0)
+#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
+#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
+#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
+
 
 /*
  * Create a UNIX-domain socket address in the Linux "abstract namespace".
     return 0;
 }
 
-static int waitfor(const char* name) {
+static void start_caml(const jbyte *name) {
+  LOGD("entry: start_caml");
+  struct sockaddr_un sockAddr;
+  socklen_t sockLen;
 
-  struct sockaddr_un server_addr;
-  socklen_t server_addr_len;
-
-  if (makeAddr(name, &server_addr, &server_addr_len) < 0)
-      return 0;
-
-  int listenfd = socket(AF_LOCAL, SOCK_STREAM, PF_UNIX);
-  if (listenfd < 0) {
-      return 0;
+  if (makeAddr(name, &sockAddr, &sockLen) < 0) {
+      LOGE("native: name creation failed");
+      return;
   }
 
-  int serverfd = 0;
-  if (bind(listenfd, (const struct sockaddr*) &server_addr, server_addr_len) < 0) {
-      perror("server bind()");
-      goto bail;
+  int fd = socket(AF_LOCAL, SOCK_STREAM, PF_UNIX);
+  if (fd < 0) {
+      LOGE("native: socket() failed");
+      return;
   }
-  if (listen(listenfd, 5) < 0) {
-      perror("server listen()");
-      goto bail;
-  }
-  serverfd = accept(listenfd, NULL, NULL);
-  if (serverfd < 0) {
-      perror("server accept");
-      serverfd = 0;
-      goto bail;
+  if (connect(fd, (const struct sockaddr*) &sockAddr, sockLen) < 0) {
+      LOGE("native: connect() failed");
+	  close (fd);
+	  return;
   }
 
-bail:
-  if(listenfd>0) close(listenfd);
+  dup2(fd, 0); // stdin  
+  dup2(fd, 1); // stdout
+  dup2(fd, 2); // stderr
 
-  return serverfd;
+  char* p = 0;
+  caml_startup(&p);
+
+  LOGD("exit successful: start_caml");
+  return;
 }
 
-static int server_inout = 0;
-static int server_err = 0;
-
-static int redirect_start() {
-
-  server_err = waitfor(SERVER_ERR);
-  if(server_err==0) return 0;
-  server_inout = waitfor(SERVER);
-  if(server_inout==0) return 0;
-
-  dup2(server_inout, 0); // stdin  
-  dup2(server_inout, 1); // stdout
-  dup2(server_err, 2); // stderr
-
-  return 1;
+JNIEXPORT jboolean JNICALL Java_jp_co_itpl_ocamlandroid_Native_start (JNIEnv *env, jclass clazz, jstring name_) {
+  LOGD("entry: prepare_stream");
+  const jbyte *name = (*env)->GetStringUTFChars(env, name_, NULL);
+  if (name == NULL) {
+    return JNI_FALSE;
+  }
+  
+  pid_t parent_pgid = getpgid(0);
+  if(parent_pgid==-1) { LOGE("getpgid failed."); }
+  
+  if(fork()==0) {
+    LOGI("child:forked caml process");
+    int res = setpgid(0, parent_pgid);
+    if(res==-1) { LOGE("setpgid failed."); }
+    start_caml(name);
+    exit(0);
+  } else {
+    LOGI("parent:forked caml process");
+  }
+  (*env)->ReleaseStringUTFChars(env, name_, name);
+  LOGD("exit successful: prepare_stream");
+  return JNI_TRUE;
 }
 
-static void redirect_end() {
-  // TODO dup2で変えたfdを元に戻す
-  if(server_err!=0) close(server_inout);
-  if(server_inout!=0) close(server_inout);
-}
-
-static void chdir_jstring(JNIEnv * env, jstring path_) {
+JNIEXPORT void JNICALL Java_jp_co_itpl_ocamlandroid_Native_chdir (JNIEnv * env, jclass clazz, jstring path_) {
+  LOGD("entry: chdir");
   const jbyte *path = (*env)->GetStringUTFChars(env, path_, NULL);
   if (path == NULL) {
       return;
   }
   chdir(path);
   (*env)->ReleaseStringUTFChars(env, path_, path);
+  LOGD("exit successful: chdir");
 }
 
-JNIEXPORT void JNICALL Java_jp_co_itpl_ocamlandroid_Native_start (JNIEnv * env, jclass clazz, jstring path) {
 
-  chdir_jstring(env, path);
-  
-  if(!redirect_start()) {
-    redirect_end(); 
-    return;
-  }
-
-  char* p = 0;
-  caml_startup(&p);
-
-  redirect_end();
-  
-}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.