[Commotion-dev] [PATCH] Refactor MeshService to support stopping olsrd.

Will Hawkins hawkinsw at opentechinstitute.org
Mon Jul 2 20:21:55 UTC 2012


Refactor MeshService.java so that we can properly
stop olsrd when the user presses Stop. This consolidates
all the process monitoring into a MeshTetherProcess
app that handles start, stop and i/o redirection.
---
 assets/do_stop_olsrd                               |    8 +
 assets/run                                         |    2 +
 assets/stop_olsrd                                  |    8 +
 .../commotionwireless/meshtether/MeshService.java  |  195 ++++++++++++++------
 .../commotionwireless/meshtether/NativeHelper.java |    6 +
 5 files changed, 160 insertions(+), 59 deletions(-)
 create mode 100644 assets/do_stop_olsrd
 create mode 100644 assets/stop_olsrd

diff --git a/assets/do_stop_olsrd b/assets/do_stop_olsrd
new file mode 100644
index 0000000..36b060f
--- /dev/null
+++ b/assets/do_stop_olsrd
@@ -0,0 +1,8 @@
+#!/system/bin/sh
+# main runner (process manager) for barnacle, root required
+
+: ${brncl_path:=.}
+
+export brncl_path
+
+kill -15 `cat $brncl_path/../app_log/olsrd.pid`
diff --git a/assets/run b/assets/run
index 3dab78a..da4c752 100644
--- a/assets/run
+++ b/assets/run
@@ -44,8 +44,10 @@ sleep 1
 
 # run olsrd
 (./olsrd -f olsrd.conf -i $brncl_if_lan > $brncl_path/../app_log/olsrd.log 2>&1) &
+echo `ps | grep olsrd | awk '{print $2;}'` > $brncl_path/../app_log/olsrd.pid
 echo "OLSR on http://${brncl_adhoc_ip}:8080"
 
+
 # the association loop
 ./wifi assoc
 
diff --git a/assets/stop_olsrd b/assets/stop_olsrd
new file mode 100644
index 0000000..7c466eb
--- /dev/null
+++ b/assets/stop_olsrd
@@ -0,0 +1,8 @@
+#!/system/bin/sh
+# main runner (process manager) for barnacle, root required
+
+: ${brncl_path:=.}
+
+export brncl_path
+
+su -c ${brncl_path}/do_stop_olsrd
diff --git a/src/net/commotionwireless/meshtether/MeshService.java b/src/net/commotionwireless/meshtether/MeshService.java
index 3012a14..85efbb7 100644
--- a/src/net/commotionwireless/meshtether/MeshService.java
+++ b/src/net/commotionwireless/meshtether/MeshService.java
@@ -18,6 +18,7 @@
 
 package net.commotionwireless.meshtether;
 
+import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -25,7 +26,6 @@ import java.util.ArrayList;
 import java.util.Map;
 
 import net.commotionwireless.meshtether.Util.MACAddress;
-import net.commotionwireless.meshtether.R;
 import android.app.Notification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -60,6 +60,7 @@ public class MeshService extends android.app.Service {
     final static int MSG_ASSOC      = 7;
     final static int MSG_STATS      = 8;
     final static int MSG_SET_DNS1_OUTPUT = 9;
+    final static int MSG_STOP_OLSRD_OUTPUT = 10;
     // app states
     public final static int STATE_STOPPED  = 0;
     public final static int STATE_STARTING = 1;
@@ -67,10 +68,8 @@ public class MeshService extends android.app.Service {
 
     // private state
     private int state = STATE_STOPPED;
-    private Process process = null; // native process for ad-hoc config
-    private Process DnsProcess = null;
-    // output monitoring threads
-    private Thread[] threads = new Thread[3];
+    private MeshTetherProcess WifiProcess = null;
+
     private PowerManager.WakeLock wakeLock;
     private BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
         @Override
@@ -206,7 +205,7 @@ public class MeshService extends android.app.Service {
             break;
         case MSG_ERROR:
             if (state == STATE_STOPPED) return;
-            if (process == null) return; // don't kill it again...
+            if (WifiProcess == null) return; // don't kill it again...
             if (msg.obj != null) {
                 String line = (String)msg.obj;
                 log(true, line); // just dump it and ignore it
@@ -257,7 +256,7 @@ public class MeshService extends android.app.Service {
         }
         case MSG_OUTPUT:
             if (state == STATE_STOPPED) return;
-            if (process == null) return; // cut the gibberish
+            if (WifiProcess == null) return; // cut the gibberish
             String line = (String)msg.obj;
             if (line == null) {
                 // ignore it, wait for MSG_ERROR(null)
@@ -303,10 +302,10 @@ public class MeshService extends android.app.Service {
         case MSG_NETSCHANGE:
             int wifiState = wifiManager.getWifiState();
             String preferredDnsValue = getPrefValue(getString(R.string.adhoc_dns_server));
-            Log.e(TAG, String.format("NETSCHANGE: %d %d %s", wifiState, state, process == null ? "null" : "proc"));
+            Log.e(TAG, String.format("NETSCHANGE: %d %d %s", wifiState, state, WifiProcess == null ? "null" : "proc"));
             if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
                 // wifi is good (or lost), we can start now...
-            	if ((state == STATE_STARTING) && (process == null)) {
+            	if ((state == STATE_STARTING) && (WifiProcess == null)) {
             		if (app.findIfWan()) {
             			// TODO if WAN found with checkUplink(), then setup Hna4 routing
             			log(false, "Found active WAN interface");
@@ -318,12 +317,9 @@ public class MeshService extends android.app.Service {
                     }
             		mOldNetDns1Value = System.getProperty("net.dns1");
             		try {
-	            		DnsProcess = Runtime.getRuntime().exec(NativeHelper.SET_NET_DNS1 + " " + preferredDnsValue,
+            			MeshTetherProcess DnsProcess = new MeshTetherProcess(NativeHelper.SET_NET_DNS1 + " " + preferredDnsValue,
 	                    		null, NativeHelper.app_bin);
-	                    threads[2] = new Thread(new OutputMonitor(MSG_SET_DNS1_OUTPUT, DnsProcess.getInputStream()));
-	                    threads[2].start();
-	                    DnsProcess.waitFor();
-	                    DnsProcess.destroy();
+            			DnsProcess.runUntilExit(mHandler, MSG_SET_DNS1_OUTPUT, MSG_SET_DNS1_OUTPUT);
 					} catch (IOException e) {
                         log(false, "Error occurred while setting DNS server: " + e.getMessage());
 						e.printStackTrace();
@@ -363,13 +359,11 @@ public class MeshService extends android.app.Service {
             stopProcess();
             if (mOldNetDns1Value != null)
             {
-            	try {
-            		DnsProcess = Runtime.getRuntime().exec(NativeHelper.SET_NET_DNS1 + " " + mOldNetDns1Value, 
-                    		null, NativeHelper.app_bin);
-                    threads[2] = new Thread(new OutputMonitor(MSG_SET_DNS1_OUTPUT, DnsProcess.getInputStream()));
-                    threads[2].start();
-                    DnsProcess.waitFor();
-                    DnsProcess.destroy();
+            	try {            		
+            		MeshTetherProcess DnsProcess = new MeshTetherProcess(NativeHelper.SET_NET_DNS1 + " " + mOldNetDns1Value, 
+            				null, NativeHelper.app_bin);
+            		DnsProcess.runUntilExit(mHandler, MSG_SET_DNS1_OUTPUT, MSG_SET_DNS1_OUTPUT);
+
 				} catch (IOException e) {
                     log(false, "Error occurred while resetting DNS server: " + e.getMessage());
 					e.printStackTrace();
@@ -434,6 +428,82 @@ public class MeshService extends android.app.Service {
             }
         }
     }
+    
+    private class MeshTetherProcess {
+    	private final static int INPUT_THREAD = 0;
+    	private final static int ERROR_THREAD = 1;
+    	
+    	private boolean mRunning;
+    	private Thread mIoThreads[] = new Thread[2];
+    	private Process mProcess = null;
+    	private String mProg;
+    	private String[] mEnvp;
+    	private File mDirectory;
+    	private int mExitValue;
+    	
+    	public MeshTetherProcess(String prog, String[] envp, File directory) {
+    		mProg = prog;
+    		mEnvp = envp;
+    		mDirectory = directory;
+    		mRunning = false;
+    		mExitValue = 0;
+    	}
+    	
+    	public void stop() throws IOException, InterruptedException {
+    		if (mProcess != null) {
+    			mProcess.getOutputStream().close();
+    			mProcess.getErrorStream().close();
+    			
+    			mIoThreads[INPUT_THREAD].interrupt();
+    			mIoThreads[ERROR_THREAD].interrupt();
+    			
+    			mIoThreads[INPUT_THREAD] = null;
+    			mIoThreads[ERROR_THREAD] = null;
+
+    			mProcess.destroy();
+    			mProcess.waitFor();
+    			mExitValue = mProcess.exitValue();
+    			mProcess = null;
+    			mRunning = false;
+    		}
+    	}
+    	
+    	public void run(Handler handler, int outputTag, int errorTag) throws IOException {
+    		mProcess = Runtime.getRuntime().exec(mProg, mEnvp, mDirectory);
+    		mIoThreads[INPUT_THREAD] = new Thread(new OutputMonitor(outputTag, mProcess.getInputStream()));
+    		mIoThreads[ERROR_THREAD] = new Thread(new OutputMonitor(errorTag, mProcess.getErrorStream()));
+    		mIoThreads[INPUT_THREAD].start();
+    		mIoThreads[ERROR_THREAD].start();
+    		mRunning = true;
+    	}
+    	
+    	public void tell(byte[] msg) throws IOException {
+    		if (mRunning)
+    			mProcess.getOutputStream().write(msg);
+    	}
+    	public void runUntilExit(Handler handler, int outputTag, int errorTag) throws IOException, InterruptedException {
+    		run(handler,outputTag,errorTag);
+    		mProcess.waitFor();
+    		
+			mIoThreads[INPUT_THREAD].interrupt();
+			mIoThreads[ERROR_THREAD].interrupt();
+			
+			mIoThreads[INPUT_THREAD] = null;
+			mIoThreads[ERROR_THREAD] = null;
+			
+    		mProcess.destroy();
+			mExitValue = mProcess.exitValue();
+
+    		mProcess = null;
+    		mRunning = false;
+    	}
+    	public int exitValue() {
+    		if (!mRunning)
+    			return mExitValue;
+    		else
+    			return 0;
+    	}
+    }
 
     private void clientAdded(ClientData cd) {
 
@@ -551,12 +621,8 @@ public class MeshService extends android.app.Service {
     	// calling 'su -c' from Java doesn't work so we use a helper script
     	String cmd = NativeHelper.SU_C;
         try {
-            process = Runtime.getRuntime().exec(cmd,
-            		buildEnvFromPrefs(), NativeHelper.app_bin);
-            threads[0] = new Thread(new OutputMonitor(MSG_OUTPUT, process.getInputStream()));
-            threads[1] = new Thread(new OutputMonitor(MSG_ERROR, process.getErrorStream()));
-            threads[0].start();
-            threads[1].start();
+        	WifiProcess = new MeshTetherProcess(cmd, buildEnvFromPrefs(), NativeHelper.app_bin);
+        	WifiProcess.run(mHandler, MSG_OUTPUT, MSG_ERROR);
         } catch (Exception e) {
             log(true, String.format(getString(R.string.execerr), cmd));
             Log.e(TAG, "start failed " + e.toString());
@@ -564,47 +630,58 @@ public class MeshService extends android.app.Service {
         }
         return true;
     }
+    
+    private void stopProcess() {
+    	/*
+    	 * TODO: UN copy and paste!!
+    	 */
+    	if (state != STATE_STOPPED) {
+    		try {	
+    			MeshTetherProcess StopOlsrProcess = new MeshTetherProcess(NativeHelper.STOP_OLSRD,
+    					null, NativeHelper.app_bin);
+    			StopOlsrProcess.runUntilExit(mHandler, MSG_STOP_OLSRD_OUTPUT, MSG_STOP_OLSRD_OUTPUT);
+
+    		} catch (IOException e) {
+    			log(false, "Error occurred while stopping Olsrd: " + e.getMessage());
+    			e.printStackTrace();
+    		} catch (InterruptedException e) {
+    			log(false, "Error occurred while stopping Olsrd: " + e.getMessage());
+    			e.printStackTrace();
+    		}
+
+    		if (WifiProcess != null) {
+    			// first, just close the stream
+    			if (state != STATE_STOPPED) {
+    				try {
+    					WifiProcess.stop();
+    				} catch (Exception e) {
+    					Log.w(TAG, "Exception while closing process");
+    				}
+    			}
+
+    			try {
+    				int exit_status = WifiProcess.exitValue();
+    				Log.i(TAG, "Wifi Process exited with status: " + exit_status);
+    			} catch (IllegalThreadStateException e) {
+    				// this is not good
+    				log(true, getString(R.string.dirtystop));
+    			}
+    			WifiProcess = null;
+    		}
+    	}
+    }
+
 
     private boolean tellProcess(String msg) {
-        if (process != null) {
+        if (WifiProcess != null) {
             try {
-                process.getOutputStream().write((msg+"\n").getBytes());
+                WifiProcess.tell((msg+"\n").getBytes());
                 return true;
             } catch (Exception e) {} // just ignore it
         }
         return false;
     }
 
-    private void stopProcess() {
-        if (process != null) {
-            // first, just close the stream
-            if (state != STATE_STOPPED) {
-                try {
-                    process.getOutputStream().close();
-                } catch (Exception e) {
-                    Log.w(TAG, "Exception while closing process");
-                }
-            }
-            try {
-                process.waitFor(); // blocking!
-            } catch (InterruptedException e) {
-                Log.e(TAG, "");
-            }
-
-            try {
-                int exit_status = process.exitValue();
-                Log.i(TAG, "Process exited with status: " + exit_status);
-            } catch (IllegalThreadStateException e) {
-                // this is not good
-                log(true, getString(R.string.dirtystop));
-            }
-            process.destroy();
-            process = null;
-            threads[0].interrupt();
-            threads[1].interrupt();
-        }
-    }
-
     @Override
     public IBinder onBind(Intent intent) {
         return null;
diff --git a/src/net/commotionwireless/meshtether/NativeHelper.java b/src/net/commotionwireless/meshtether/NativeHelper.java
index e72597b..bedc6d6 100644
--- a/src/net/commotionwireless/meshtether/NativeHelper.java
+++ b/src/net/commotionwireless/meshtether/NativeHelper.java
@@ -27,6 +27,8 @@ public class NativeHelper {
 
     static String SU_C;
     static String RUN;
+    static String STOP_OLSRD;
+    static String DO_STOP_OLSRD;
     static String OLSRD;
     static String WIFI;
     static String SET_NET_DNS1;
@@ -38,6 +40,8 @@ public class NativeHelper {
 		publicFiles = new File(Environment.getExternalStorageDirectory(),
 				"Android/data/" + context.getPackageName() + "/files/");
 		SU_C = new File(app_bin, "su_c").getAbsolutePath();
+		STOP_OLSRD = new File(app_bin, "stop_olsrd").getAbsolutePath();
+		DO_STOP_OLSRD = new File(app_bin, "do_stop_olsrd").getAbsolutePath();
 		RUN = new File(app_bin, "run").getAbsolutePath();
 		OLSRD = new File(app_bin, "olsrd").getAbsolutePath();
 		WIFI = new File(app_bin, "wifi").getAbsolutePath();
@@ -86,6 +90,8 @@ public class NativeHelper {
 		}
 		chmod("0750", new File(SU_C));
 		chmod("0750", new File(RUN));
+		chmod("0750", new File(STOP_OLSRD));
+		chmod("0750", new File(DO_STOP_OLSRD));
 		chmod("0750", new File(OLSRD));
 		chmod("0750", new File(WIFI));
 		chmod("0750", new File(SET_NET_DNS1));
-- 
1.7.9.5



More information about the Commotion-dev mailing list