[tbb-commits] [tor-browser] 04/10: fixup! Bug 40933: Add tor-launcher functionality
gitolite role
git at cupani.torproject.org
Mon Oct 10 20:17:18 UTC 2022
This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch tor-browser-102.3.0esr-12.0-2
in repository tor-browser.
commit 1a64d858c5ab472eec6fc48a43b9ff54942971a5
Author: Pier Angelo Vendrame <pierov at torproject.org>
AuthorDate: Mon Oct 10 15:26:50 2022 +0200
fixup! Bug 40933: Add tor-launcher functionality
Bug 40853: Use Subprocess.jsm to launch tor.
---
.../components/tor-launcher/TorMonitorService.jsm | 16 +-
toolkit/components/tor-launcher/TorProcess.jsm | 205 +++++++++++----------
2 files changed, 110 insertions(+), 111 deletions(-)
diff --git a/toolkit/components/tor-launcher/TorMonitorService.jsm b/toolkit/components/tor-launcher/TorMonitorService.jsm
index 16d7fc927adc..201ac6275c56 100644
--- a/toolkit/components/tor-launcher/TorMonitorService.jsm
+++ b/toolkit/components/tor-launcher/TorMonitorService.jsm
@@ -103,6 +103,10 @@ const TorMonitorService = {
// control connection is closed. Therefore, as a matter of facts, calling this
// function also makes the child Tor instance stop.
uninit() {
+ if (this._torProcess) {
+ this._torProcess.forget();
+ this._torProcess = null;
+ }
this._shutDownEventMonitor();
},
@@ -179,12 +183,11 @@ const TorMonitorService = {
async _startProcess() {
this._torProcess = new TorProcess();
- this._torProcess.onExit = unexpected => {
- this._shutDownEventMonitor(!unexpected);
+ this._torProcess.onExit = () => {
Services.obs.notifyObservers(null, TorTopics.ProcessExited);
};
this._torProcess.onRestart = async () => {
- this._shutDownEventMonitor(false);
+ this._shutDownEventMonitor();
await this._controlTor();
Services.obs.notifyObservers(null, TorTopics.ProcessRestarted);
};
@@ -434,13 +437,8 @@ const TorMonitorService = {
}
},
- _shutDownEventMonitor(shouldCallStop = true) {
+ _shutDownEventMonitor() {
if (this._connection) {
- if (this.ownsTorDaemon && this._torProcess && shouldCallStop) {
- this._torProcess.stop();
- this._torProcess = null;
- }
-
this._connection.close();
this._connection = null;
this._eventMonitorInProgressReply = null;
diff --git a/toolkit/components/tor-launcher/TorProcess.jsm b/toolkit/components/tor-launcher/TorProcess.jsm
index 78bf2504c9b6..a23fd324efff 100644
--- a/toolkit/components/tor-launcher/TorProcess.jsm
+++ b/toolkit/components/tor-launcher/TorProcess.jsm
@@ -8,6 +8,10 @@ const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
+const { Subprocess } = ChromeUtils.import(
+ "resource://gre/modules/Subprocess.jsm"
+);
+
ChromeUtils.defineModuleGetter(
this,
"TorProtocolService",
@@ -32,11 +36,6 @@ const TorProcessTopics = Object.freeze({
ProcessDidNotStart: "TorProcessDidNotStart",
});
-const ProcessTopics = Object.freeze({
- ProcessFailed: "process-failed",
- ProcessFinished: "process-finished",
-});
-
// Logger adapted from CustomizableUI.jsm
XPCOMUtils.defineLazyGetter(this, "logger", () => {
const { ConsoleAPI } = ChromeUtils.import(
@@ -73,15 +72,6 @@ class TorProcess {
);
}
- observe(aSubject, aTopic, aParam) {
- if (
- ProcessTopics.ProcessFailed === aTopic ||
- ProcessTopics.ProcessFinished === aTopic
- ) {
- this._processExited();
- }
- }
-
async start() {
if (this._torProcess) {
return;
@@ -112,31 +102,27 @@ class TorProcess {
// Set an environment variable that points to the Tor data directory.
// This is used by meek-client-torbrowser to find the location for
// the meek browser profile.
- const env = Cc["@mozilla.org/process/environment;1"].getService(
- Ci.nsIEnvironment
- );
- env.set("TOR_BROWSER_TOR_DATA_DIR", this._dataDir.path);
+ const environment = {
+ TOR_BROWSER_TOR_DATA_DIR: this._dataDir.path,
+ };
// On Windows, prepend the Tor program directory to PATH. This is needed
// so that pluggable transports can find OpenSSL DLLs, etc.
// See https://trac.torproject.org/projects/tor/ticket/10845
if (TorLauncherUtil.isWindows) {
let path = this._exeFile.parent.path;
+ const env = Cc["@mozilla.org/process/environment;1"].getService(
+ Ci.nsIEnvironment
+ );
if (env.exists("PATH")) {
path += ";" + env.get("PATH");
}
- env.set("PATH", path);
+ environment.PATH = path;
}
this._status = TorProcessStatus.Starting;
this._didConnectToTorControlPort = false;
- var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
- p.startHidden = true;
- p.init(this._exeFile);
-
- logger.debug(`Starting ${this._exeFile.path}`, this._args);
-
// useful for simulating slow tor daemon launch
const kPrefTorDaemonLaunchDelay = "extensions.torlauncher.launch_delay";
const launchDelay = Services.prefs.getIntPref(
@@ -146,46 +132,48 @@ class TorProcess {
if (launchDelay > 0) {
await new Promise(resolve => setTimeout(() => resolve(), launchDelay));
}
- p.runwAsync(this._args, this._args.length, this, false);
- // FIXME: This should be okay, unless the observer is called just before
- // assigning the correct state.
- // We should check for the control connection status, rather than the
- // process status.
- if (this._status === TorProcessStatus.Starting) {
- this._status = TorProcessStatus.Running;
- }
- this._torProcess = p;
+ logger.debug(`Starting ${this._exeFile.path}`, this._args);
+ const options = {
+ command: this._exeFile.path,
+ arguments: this._args,
+ environment,
+ environmentAppend: true,
+ stderr: "pipe",
+ };
+ this._torProcess = await Subprocess.call(options);
+ this._watchProcess();
+ this._status = TorProcessStatus.Running;
this._torProcessStartTime = Date.now();
} catch (e) {
this._status = TorProcessStatus.Exited;
- const s = TorLauncherUtil.getLocalizedString("tor_failed_to_start");
- TorLauncherUtil.notifyUserOfError(
- s,
+ this._torProcess = null;
+ logger.error("startTor error:", e);
+ Services.obs.notifyObservers(
null,
- TorProcessTopics.ProcessDidNotStart
+ TorProcessTopics.ProcessDidNotStart,
+ null
);
- logger.error("startTor error:", e);
}
}
- stop() {
- if (this._torProcess) {
- // We now rely on the TAKEOWNERSHIP feature to shut down tor when we
- // close the control port connection.
- //
- // Previously, we sent a SIGNAL HALT command to the tor control port,
- // but that caused hangs upon exit in the Firefox 24.x based browser.
- // Apparently, Firefox does not like to process socket I/O while
- // quitting if the browser did not finish starting up (e.g., when
- // someone presses the Quit button on our Network Settings window
- // during startup).
- //
- // However, we set the Subprocess object to null to distinguish the cases
- // in which we wanted to explicitly kill the tor process, from the cases
- // in which it exited for any other reason, e.g., a crash.
- this._torProcess = null;
- }
+ // Forget about a process.
+ //
+ // Instead of killing the tor process, we rely on the TAKEOWNERSHIP feature
+ // to shut down tor when we close the control port connection.
+ //
+ // Previously, we sent a SIGNAL HALT command to the tor control port,
+ // but that caused hangs upon exit in the Firefox 24.x based browser.
+ // Apparently, Firefox does not like to process socket I/O while
+ // quitting if the browser did not finish starting up (e.g., when
+ // someone presses the Quit button on our Network Settings window
+ // during startup).
+ //
+ // Still, before closing the owning connection, this class should forget about
+ // the process, so that future notifications will be ignored.
+ forget() {
+ this._torProcess = null;
+ this._status = TorProcessStatus.Exited;
}
// The owner of the process can use this function to tell us that they
@@ -195,58 +183,71 @@ class TorProcess {
this._didConnectToTorControlPort = true;
}
- _processExited() {
- // When we stop tor intentionally, we also set _torProcess to null.
- // So, if this._torProcess is not null, it exited for some other reason.
- const unexpected = !!this._torProcess;
- if (unexpected) {
- logger.warn("The tor process exited unexpectedly.");
- } else {
- logger.info("The tor process exited.");
+ async _watchProcess() {
+ const watched = this._torProcess;
+ if (!watched) {
+ return;
}
+ try {
+ const { exitCode } = await watched.wait();
- this._torProcess = null;
- this._status = TorProcessStatus.Exited;
-
- let restart = false;
- if (unexpected) {
- // TODO: Move this logic somewhere else?
- let s;
- if (!this._didConnectToTorControlPort) {
- // tor might be misconfigured, becauser we could never connect to it
- const key = "tor_exited_during_startup";
- s = TorLauncherUtil.getLocalizedString(key);
+ if (watched !== this._torProcess) {
+ logger.debug(`A Tor process exited with code ${exitCode}.`);
+ } else if (exitCode) {
+ logger.warn(`The watched Tor process exited with code ${exitCode}.`);
} else {
- // tor exited suddenly, so configuration should be okay
- s =
- TorLauncherUtil.getLocalizedString("tor_exited") +
- "\n\n" +
- TorLauncherUtil.getLocalizedString("tor_exited2");
+ logger.info("The Tor process exited.");
}
- logger.info(s);
- var defaultBtnLabel = TorLauncherUtil.getLocalizedString("restart_tor");
- var cancelBtnLabel = "OK";
- try {
- const kSysBundleURI = "chrome://global/locale/commonDialogs.properties";
- var sysBundle = Services.strings.createBundle(kSysBundleURI);
- cancelBtnLabel = sysBundle.GetStringFromName(cancelBtnLabel);
- } catch (e) {}
+ } catch (e) {
+ logger.error("Failed to watch the tor process", e);
+ }
- restart = TorLauncherUtil.showConfirm(
- null,
- s,
- defaultBtnLabel,
- cancelBtnLabel
- );
- if (restart) {
- this.start().then(() => {
- if (this.onRestart) {
- this.onRestart();
- }
- });
- }
+ if (watched === this._torProcess) {
+ this._processExitedUnexpectedly();
}
- if (!restart && this.onExit) {
+ }
+
+ _processExitedUnexpectedly() {
+ this._torProcess = null;
+ this._status = TorProcessStatus.Exited;
+
+ // TODO: Move this logic somewhere else?
+ let s;
+ if (!this._didConnectToTorControlPort) {
+ // tor might be misconfigured, becauser we could never connect to it
+ const key = "tor_exited_during_startup";
+ s = TorLauncherUtil.getLocalizedString(key);
+ } else {
+ // tor exited suddenly, so configuration should be okay
+ s =
+ TorLauncherUtil.getLocalizedString("tor_exited") +
+ "\n\n" +
+ TorLauncherUtil.getLocalizedString("tor_exited2");
+ }
+ logger.info(s);
+ const defaultBtnLabel = TorLauncherUtil.getLocalizedString("restart_tor");
+ let cancelBtnLabel = "OK";
+ try {
+ const kSysBundleURI = "chrome://global/locale/commonDialogs.properties";
+ const sysBundle = Services.strings.createBundle(kSysBundleURI);
+ cancelBtnLabel = sysBundle.GetStringFromName(cancelBtnLabel);
+ } catch (e) {
+ logger.warn("Could not localize the cancel button", e);
+ }
+
+ const restart = TorLauncherUtil.showConfirm(
+ null,
+ s,
+ defaultBtnLabel,
+ cancelBtnLabel
+ );
+ if (restart) {
+ this.start().then(() => {
+ if (this.onRestart) {
+ this.onRestart();
+ }
+ });
+ } else if (this.onExit) {
this.onExit(unexpected);
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the tbb-commits
mailing list