diff --git a/tor-android-binary/src/main/java/org/torproject/jni/TorService.java b/tor-android-binary/src/main/java/org/torproject/jni/TorService.java
index c1f4c77077ad6deddc3ed59f9704f2483d2bcb5e..cf97711584c6567c6577bbaac6c117f79a257c75 100644
--- a/tor-android-binary/src/main/java/org/torproject/jni/TorService.java
+++ b/tor-android-binary/src/main/java/org/torproject/jni/TorService.java
@@ -266,7 +266,7 @@ public class TorService extends Service {
      * 10 seconds, after that it will check whether the {@code ControlSocket}
      * file exists, and if not, throw a {@link IllegalStateException}.
      */
-    private Thread controlPortThread = new Thread(CONTROL_SOCKET_NAME) {
+    private final Thread controlPortThread = new Thread(CONTROL_SOCKET_NAME) {
         @Override
         public void run() {
             android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -287,7 +287,7 @@ public class TorService extends Service {
                 controlPortFileObserver.stopWatching();
                 File controlSocket = new File(observeDir, CONTROL_SOCKET_NAME);
                 if (!controlSocket.canRead()) {
-                    throw new IllegalStateException("cannot read " + controlSocket);
+                    throw new IOException("cannot read " + controlSocket);
                 }
 
                 FileDescriptor controlSocketFd = prepareFileDescriptor(getControlSocket(TorService.this).getAbsolutePath());
@@ -304,14 +304,86 @@ public class TorService extends Service {
 
             } catch (IOException | ArrayIndexOutOfBoundsException | InterruptedException e) {
                 e.printStackTrace();
+                broadcastError(TorService.this, e);
                 broadcastStatus(TorService.this, STATUS_STOPPING);
-                TorService.this.stopSelf();
+                stopSelf();
             }
         }
     };
 
     private volatile CountDownLatch controlPortThreadStarted;
 
+    private final Thread torThread = new Thread("tor") {
+        @Override
+        public void run() {
+            final Context context = getApplicationContext();
+            try {
+                String socksPort = "auto";
+                if (isPortAvailable(9050)) {
+                    socksPort = Integer.toString(9050);
+                }
+                String httpTunnelPort = "auto";
+                if (isPortAvailable(8118)) {
+                    httpTunnelPort = Integer.toString(8118);
+                }
+
+                createTorConfiguration();
+                ArrayList<String> lines = new ArrayList<>(Arrays.asList("tor", "--verify-config", // must always be here
+                        "--RunAsDaemon", "0",
+                        "-f", getTorrc(context).getAbsolutePath(),
+                        "--defaults-torrc", getDefaultsTorrc(context).getAbsolutePath(),
+                        "--ignore-missing-torrc",
+                        "--SyslogIdentityTag", TAG,
+                        "--CacheDirectory", new File(getCacheDir(), TAG).getAbsolutePath(),
+                        "--DataDirectory", getAppTorServiceDataDir(context).getAbsolutePath(),
+                        "--ControlSocket", getControlSocket(context).getAbsolutePath(),
+                        "--CookieAuthentication", "0",
+                        "--SOCKSPort", socksPort,
+                        "--HTTPTunnelPort", httpTunnelPort,
+
+                        // can be moved to ControlPort messages
+                        "--LogMessageDomains", "1",
+                        "--TruncateLogFile", "1"
+                ));
+                String[] verifyLines = lines.toArray(new String[0]);
+                if (!mainConfigurationSetCommandLine(verifyLines)) {
+                    throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(verifyLines));
+                }
+                int result = runMain(); // run verify
+                if (result != 0) {
+                    throw new IllegalArgumentException("Bad command flags: " + Arrays.toString(verifyLines));
+                }
+
+                controlPortThreadStarted = new CountDownLatch(1);
+                controlPortThread.start();
+                controlPortThreadStarted.await();
+
+                String[] runLines = new String[lines.size() - 1];
+                runLines[0] = "tor";
+                for (int i = 2; i < lines.size(); i++) {
+                    runLines[i - 1] = lines.get(i);
+                }
+                if (!mainConfigurationSetCommandLine(runLines)) {
+                    throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(runLines));
+                }
+                if (!mainConfigurationSetupControlSocket()) {
+                    throw new IllegalStateException("Setting up ControlPort failed!");
+                }
+                if (runMain() != 0) {
+                    throw new IllegalStateException("Tor could not start!");
+                }
+
+            } catch (IllegalStateException | IllegalArgumentException | InterruptedException e) {
+                e.printStackTrace();
+                broadcastError(context, e);
+            } finally {
+                broadcastStatus(context, STATUS_STOPPING);
+                mainConfigurationFree();
+                TorService.this.stopSelf();
+            }
+        }
+    };
+
     private int getPortFromGetInfo(String key) {
         final String value = getInfo(key);
         return Integer.parseInt(value.substring(value.lastIndexOf(':') + 1, value.length() - 1));
@@ -334,83 +406,12 @@ public class TorService extends Service {
      * @see <a href="https://github.com/torproject/tor/blob/40be20d542a83359ea480bbaa28380b4137c88b2/src/app/config/config.c#L4730">options that must be on the command line</a>
      */
     private void startTorServiceThread() {
-        final Context context = this.getApplicationContext();
-        new Thread("tor") {
-            @Override
-            public void run() {
-                try {
-                    String socksPort = "auto";
-                    if (isPortAvailable(9050)) {
-                        socksPort = Integer.toString(9050);
-                    }
-                    String httpTunnelPort = "auto";
-                    if (isPortAvailable(8118)) {
-                        httpTunnelPort = Integer.toString(8118);
-                    }
-
-                    if (runLock.isLocked()) {
-                        Log.i(TAG, "Waiting for lock");
-                    }
-                    runLock.lock();
-                    Log.i(TAG, "Acquired lock");
-                    createTorConfiguration();
-                    ArrayList<String> lines = new ArrayList<>(Arrays.asList("tor", "--verify-config", // must always be here
-                            "--RunAsDaemon", "0",
-                            "-f", getTorrc(context).getAbsolutePath(),
-                            "--defaults-torrc", getDefaultsTorrc(context).getAbsolutePath(),
-                            "--ignore-missing-torrc",
-                            "--SyslogIdentityTag", TAG,
-                            "--CacheDirectory", new File(getCacheDir(), TAG).getAbsolutePath(),
-                            "--DataDirectory", getAppTorServiceDataDir(context).getAbsolutePath(),
-                            "--ControlSocket", getControlSocket(context).getAbsolutePath(),
-                            "--CookieAuthentication", "0",
-                            "--SOCKSPort", socksPort,
-                            "--HTTPTunnelPort", httpTunnelPort,
-
-                            // can be moved to ControlPort messages
-                            "--LogMessageDomains", "1",
-                            "--TruncateLogFile", "1"
-                    ));
-                    String[] verifyLines = lines.toArray(new String[0]);
-                    if (!mainConfigurationSetCommandLine(verifyLines)) {
-                        throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(verifyLines));
-                    }
-                    int result = runMain(); // run verify
-                    if (result != 0) {
-                        throw new IllegalArgumentException("Bad command flags: " + Arrays.toString(verifyLines));
-                    }
-
-                    controlPortThreadStarted = new CountDownLatch(1);
-                    controlPortThread.start();
-                    controlPortThreadStarted.await();
-
-                    String[] runLines = new String[lines.size() - 1];
-                    runLines[0] = "tor";
-                    for (int i = 2; i < lines.size(); i++) {
-                        runLines[i - 1] = lines.get(i);
-                    }
-                    if (!mainConfigurationSetCommandLine(runLines)) {
-                        throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(runLines));
-                    }
-                    if (!mainConfigurationSetupControlSocket()) {
-                        throw new IllegalStateException("Setting up ControlPort failed!");
-                    }
-                    if (runMain() != 0) {
-                        throw new IllegalStateException("Tor could not start!");
-                    }
-
-                } catch (IllegalStateException | IllegalArgumentException | InterruptedException e) {
-                    e.printStackTrace();
-                    broadcastError(context, e);
-                } finally {
-                    broadcastStatus(context, STATUS_STOPPING);
-                    mainConfigurationFree();
-                    Log.i(TAG, "Releasing lock");
-                    runLock.unlock();
-                    TorService.this.stopSelf();
-                }
-            }
-        }.start();
+        if (runLock.isLocked()) {
+            Log.i(TAG, "Waiting for lock");
+        }
+        runLock.lock();
+        Log.i(TAG, "Acquired lock");
+        torThread.start();
     }
 
     @Override
@@ -419,6 +420,10 @@ public class TorService extends Service {
         if (torControlConnection != null) {
             torControlConnection.removeRawEventListener(startedEventListener);
         }
+        if (runLock.isLocked()) {
+            Log.i(TAG, "Releasing lock");
+            runLock.unlock();
+        }
         shutdownTor(TorControlCommands.SIGNAL_SHUTDOWN);
         broadcastStatus(TorService.this, STATUS_OFF);
     }