Skip to content

[💡 Feature]: BrowserStack Local binary not terminated when WDIO process is interrupted (Ctrl+C / SIGINT) #14924

@BosseKarat

Description

@BosseKarat

Is your feature request related to a problem?

When running WDIO tests with browserstackLocal: true and the test execution is interrupted via Ctrl+C (SIGINT) or killed externally, the BrowserStack Local binary process (BrowserStackLocal.exe on Windows, BrowserStackLocal on macOS/Linux) remains running in the background as an orphaned process.

Impact:

  • Resource leakage: The tunnel process continues consuming system resources (memory, network connections, file handles)
  • Port conflicts: Subsequent test runs may fail because the port is already in use by the orphaned tunnel
  • Manual cleanup required: Users must manually kill the process via Task Manager (Windows) or Activity Monitor (macOS) after every interrupted test run
  • CI/CD issues: In automated environments, orphaned processes accumulate over time, eventually exhausting system resources

The @wdio/browserstack-service launcher correctly starts and stops BrowserStack Local during normal test completion (via onComplete hook), but does not register signal handlers for process interruption (SIGINT/SIGTERM).

When a user press Ctrl+C:

  • Node.js sends SIGINT to the WDIO process
  • WDIO terminates immediately
  • The onComplete hook never executes (async hooks don't run during synchronous termination)
  • BrowserStack Local binary remains running

How to reproduce:

  1. Start WDIO tests with BrowserStack Local enabled
  2. Wait for tunnel to connect and the tests to start running
  3. Press Ctrl+C to interrupt the test run (during runtime)
  4. Open Task Manager (Windows) or Activity Monitor (macOS)
  5. Observe: BrowserStackLocal.exe / BrowserStackLocal process is still running

Describe the solution you'd like.

When the WDIO process receives SIGINT/SIGTERM (Ctrl+C):

  1. The BrowserStack service should catch the termination signal
  2. Gracefully stop the BrowserStack Local binary before WDIO exits
  3. Clean up all related resources
  4. Exit completely without orphaned processes

Describe alternatives you've considered.

This is the workaround that I'm currently using in my config:

import { execSync } from 'child_process';

const cleanupBrowserStackLocal = () => {
        try {
            execSync('taskkill /F /IM BrowserStackLocal.exe', { stdio: 'inherit' });
        } catch (error) {
            // Every child process has already been terminated
        }
    } else {
        try {
            execSync('pkill -f BrowserStackLocal', { stdio: 'inherit' });
        } catch (error) {
           // Every child process has already been terminated
        }
};

let cleanupRegistered = false;
if (!cleanupRegistered) {
    process.on('SIGINT', () => {
        console.log(' - (Ctrl+C), cleaning up...');
        cleanupBrowserStackLocal();
        process.exit(130);
    });

    process.on('SIGTERM', () => {
        console.log('cleaning up...');
        cleanupBrowserStackLocal();
        process.exit(143);
    });

    cleanupRegistered = true;
}

Additional context

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Idea 💡A new feature ideaNeeds Triaging ⏳No one has looked into the issue yet

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions