mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
If a Tor process is left behind after a crash, kill it when restarting.
This commit is contained in:
@@ -334,7 +334,8 @@ public class HomeScreenActivity extends RoboActivity {
|
|||||||
syncButton.setText(R.string.synchronize_button);
|
syncButton.setText(R.string.synchronize_button);
|
||||||
syncButton.setOnClickListener(new OnClickListener() {
|
syncButton.setOnClickListener(new OnClickListener() {
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
// FIXME: Hook this button up to an activity
|
// FIXME: Crash testing, remove this
|
||||||
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
buttons.add(syncButton);
|
buttons.add(syncButton);
|
||||||
|
|||||||
@@ -114,10 +114,20 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
|
|
||||||
public boolean start() throws IOException {
|
public boolean start() throws IOException {
|
||||||
// Try to connect to an existing Tor process if there is one
|
// Try to connect to an existing Tor process if there is one
|
||||||
|
boolean startProcess = false;
|
||||||
try {
|
try {
|
||||||
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Tor is already running");
|
if(LOG.isLoggable(INFO)) LOG.info("Tor is already running");
|
||||||
|
if(readPidFile() == -1) {
|
||||||
|
controlSocket.close();
|
||||||
|
killZombieProcess();
|
||||||
|
startProcess = true;
|
||||||
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info("Tor is not running");
|
||||||
|
startProcess = true;
|
||||||
|
}
|
||||||
|
if(startProcess) {
|
||||||
// Install the binary, GeoIP database and config file if necessary
|
// Install the binary, GeoIP database and config file if necessary
|
||||||
if(!isInstalled() && !install()) {
|
if(!isInstalled() && !install()) {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Could not install Tor");
|
if(LOG.isLoggable(INFO)) LOG.info("Could not install Tor");
|
||||||
@@ -171,13 +181,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
||||||
}
|
}
|
||||||
// Read the PID of the Tor process so we can kill it if necessary
|
// Read the PID of the Tor process so we can kill it if necessary
|
||||||
try {
|
pid = readPidFile();
|
||||||
pid = Integer.parseInt(new String(read(pidFile), "UTF-8").trim());
|
|
||||||
} catch(IOException e) {
|
|
||||||
if(LOG.isLoggable(WARNING)) LOG.warning("Could not read PID file");
|
|
||||||
} catch(NumberFormatException e) {
|
|
||||||
if(LOG.isLoggable(WARNING)) LOG.warning("Could not parse PID file");
|
|
||||||
}
|
|
||||||
// Create a shutdown hook to ensure the Tor process is killed
|
// Create a shutdown hook to ensure the Tor process is killed
|
||||||
shutdownManager.addShutdownHook(new Runnable() {
|
shutdownManager.addShutdownHook(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -332,6 +336,58 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int readPidFile() {
|
||||||
|
// Read the PID of the Tor process so we can kill it if necessary
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(new String(read(pidFile), "UTF-8").trim());
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(WARNING)) LOG.warning("Could not read PID file");
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
if(LOG.isLoggable(WARNING)) LOG.warning("Could not parse PID file");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the app crashes, leaving a Tor process running, and the user clears
|
||||||
|
* the app's data, removing the PID file and auth cookie file, it's no
|
||||||
|
* longer possible to communicate with the zombie process and it must be
|
||||||
|
* killed. ActivityManager.killBackgroundProcesses() doesn't seem to work
|
||||||
|
* in this case, so we must parse the output of ps to get the PID.
|
||||||
|
* <p>
|
||||||
|
* On all tested devices, the output consists of a header line followed by
|
||||||
|
* one line per process. The second column is the PID and the last column
|
||||||
|
* is the process name, which includes the app's package name.
|
||||||
|
*/
|
||||||
|
private void killZombieProcess() {
|
||||||
|
String packageName = "/" + appContext.getPackageName() + "/";
|
||||||
|
try {
|
||||||
|
// Parse the output of ps
|
||||||
|
Process ps = Runtime.getRuntime().exec("ps");
|
||||||
|
Scanner scanner = new Scanner(ps.getInputStream());
|
||||||
|
// Discard the header line
|
||||||
|
if(scanner.hasNextLine()) scanner.nextLine();
|
||||||
|
// Look for a Tor process with our package name
|
||||||
|
while(scanner.hasNextLine()) {
|
||||||
|
String[] columns = scanner.nextLine().split("\\s+");
|
||||||
|
if(columns.length < 3) break;
|
||||||
|
int pid = Integer.parseInt(columns[1]);
|
||||||
|
String name = columns[columns.length - 1];
|
||||||
|
if(name.contains(packageName) && name.endsWith("/tor")) {
|
||||||
|
if(LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Killing zombie process " + pid);
|
||||||
|
android.os.Process.killProcess(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scanner.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(WARNING))
|
||||||
|
LOG.warning("Could not parse ps output");
|
||||||
|
} catch(SecurityException e) {
|
||||||
|
if(LOG.isLoggable(WARNING)) LOG.warning("Could not execute ps");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = callback.getConfig().get("port");
|
String portString = callback.getConfig().get("port");
|
||||||
|
|||||||
Reference in New Issue
Block a user