feat: Make sure all active sessions are cleaned up properly after a termination signal is received
MODIFY
lib/appium.js
lib/appium.js
@@ -311,13 +311,7 @@ class AppiumDriver extends BaseDriver {
this.printNewSessionAnnouncement(InnerDriver.name, driverVersion);
if (this.args.sessionOverride) {
- const sessionIdsToDelete = await sessionsListGuard.acquire(AppiumDriver.name, () => _.keys(this.sessions));
- if (sessionIdsToDelete.length) {
- log.info(`Session override is on. Deleting other ${sessionIdsToDelete.length} active session${sessionIdsToDelete.length ? '' : 's'}.`);
- try {
- await B.map(sessionIdsToDelete, (id) => this.deleteSession(id));
- } catch (ign) {}
- }
+ await this.deleteAllSessions();
}
let runningDriversData, otherPendingDriversData;
@@ -490,6 +484,30 @@ class AppiumDriver extends BaseDriver {
}
}
+ async deleteAllSessions (opts = {}) {
+ const sessionsCount = _.size(this.sessions);
+ if (0 === sessionsCount) {
+ log.debug('There are no active sessions for cleanup');
+ return;
+ }
+
+ const {
+ force = false,
+ reason,
+ } = opts;
+ log.debug(`Cleaning up ${sessionsCount} active session` + (sessionsCount === 1 ? '' : 's'));
+ const cleanupPromises = force
+ ? _.values(this.sessions).map((drv) => drv.startUnexpectedShutdown(reason && new Error(reason)))
+ : _.keys(this.sessions).map((id) => this.deleteSession(id));
+ for (const cleanupPromise of cleanupPromises) {
+ try {
+ await cleanupPromise;
+ } catch (e) {
+ log.debug(e);
+ }
+ }
+ }
+
async executeCommand (cmd, ...args) {
// getStatus command should not be put into queue. If we do it as part of super.executeCommand, it will be added to queue.
// There will be lot of status commands in queue during createSession command, as createSession can take up to or more than a minute.

MODIFY
lib/main.js
lib/main.js
@@ -141,15 +141,22 @@ async function main (args = null) {
throw err;
}
- process.once('SIGINT', async function onSigint () {
- logger.info(`Received SIGINT - shutting down`);
- await server.close();
+ for (const signal of ['SIGINT', 'SIGTERM']) {
+ process.once(signal, async function onSignal () {
+ logger.info(`Received ${signal} - shutting down`);
+ try {
+ await appiumDriver.deleteAllSessions({
+ force: true,
+ reason: `The process has received ${signal} signal`,
});
-
- process.once('SIGTERM', async function onSigterm () {
- logger.info(`Received SIGTERM - shutting down`);
await server.close();
+ process.exit(0);
+ } catch (e) {
+ logger.warn(e);
+ process.exit(1);
+ }
});
+ }
logServerPort(args.address, args.port);

feat: Make sure all active sessions are cleaned up properly after a termination signal is received (#13913)