diff --git a/lib/uiautomator2.js b/lib/uiautomator2.js index 21898f2c7..45adf93d5 100644 --- a/lib/uiautomator2.js +++ b/lib/uiautomator2.js @@ -305,10 +305,37 @@ class UiAutomator2Server { async cleanupAutomationLeftovers (strictCleanup = false) { this.log.debug(`Performing ${strictCleanup ? 'strict' : 'shallow'} cleanup of automation leftovers`); + const axiosTimeout = 500; + + const waitStop = async () => { + // Wait for the process stop by sending a status request to the port. + // We observed the process stop could be delayed, thus causing unexpected crashes + // in the middle of the session preparation process. It caused an invalid session error response + // by the uia2 server, but that was because the process stop's delay. + const timeout = 3000; + try { + await waitForCondition(async () => { + try { + await axios({ + url: `http://${this.host}:${this.systemPort}/status`, + timeout: axiosTimeout, + }); + } catch (err) { + return true; + } + }, { + waitMs: timeout, + intervalMs: 100, + }); + } catch (err) { + this.log.warn(`The ${SERVER_TEST_PACKAGE_ID} process might fail to stop within ${timeout}ms timeout.`); + } + }; + try { const {value} = (await axios({ url: `http://${this.host}:${this.systemPort}/sessions`, - timeout: 500, + timeout: axiosTimeout, })).data; const activeSessionIds = value.map(({id}) => id).filter(Boolean); if (activeSessionIds.length) { @@ -329,13 +356,13 @@ class UiAutomator2Server { try { await this.adb.forceStop(SERVER_TEST_PACKAGE_ID); } catch (ignore) {} - if (!strictCleanup) { - return; + if (strictCleanup) { + // https://github.com/appium/appium/issues/10749 + try { + await this.adb.killProcessesByName('uiautomator'); + } catch (ignore) {} } - // https://github.com/appium/appium/issues/10749 - try { - await this.adb.killProcessesByName('uiautomator'); - } catch (ignore) {} + await waitStop(); } }