Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Playwright can not close the browser when running with Chrome (no-headless mode) #5327

Open
honglax opened this issue Feb 5, 2021 · 26 comments

Comments

@honglax
Copy link

honglax commented Feb 5, 2021

Context:

  • Playwright Version: 1.8.0
  • Operating System: macOS 11.2
  • Node.js version: 12.18.4
  • Browser: Chrome (version 88.0.4324.146)
  • Extra: None

Code Snippet

const playwright = require('playwright')

(async () => {
  const browser = await playwright['chromium'].launch({
    executablePath:
      '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
    headless: false,
  })
  const context = await browser.newContext()
  const page = await context.newPage()
  await page.goto('https://google.com', { waitUntil: 'load' })
  const cookies = await page.context().cookies()
  await browser.close()
})()

Describe the bug
When running the test with no-headless Chrome (also happens with Chrome Dev, and Chrome Canary), the test is hung at await browser.close() and can not close the browser.

@phileba
Copy link

phileba commented Feb 5, 2021

I also got this issue

@dgozman
Copy link
Contributor

dgozman commented Feb 5, 2021

Note that Playwright is only guaranteed to work with bundled browsers, so I expect some internal protocol mismatch. That said, if you could generate protocol logs for us, we would look into them for more details. For that, run with two environment variables and copy mylog.txt here.

$ DEBUG=pw:protocol DEBUG_FILE=mylog.txt node myscript.js

@honglax
Copy link
Author

honglax commented Feb 7, 2021

Note that Playwright is only guaranteed to work with bundled browsers, so I expect some internal protocol mismatch. That said, if you could generate protocol logs for us, we would look into them for more details. For that, run with two environment variables and copy mylog.txt here.

$ DEBUG=pw:protocol DEBUG_FILE=mylog.txt node myscript.js

Here it is.
chrome-bug.txt

@dgozman
Copy link
Contributor

dgozman commented Feb 8, 2021

Logs indicate there were no issues while handling the Browser.close command. I also tried this script with Chrome Canary (version 90.0.4412.0) on MacOS 10.15 and everything works.

Did you try playwright v1.6? It roughly corresponds to Chromium 88.0.4316.0, so I expect things to work there. Overall, you can find out the version of bundled browsers in our (release notes)[https://github.com/microsoft/playwright/releases]. We usually expect similar version to work with Playwright, but older versions might break.

@pohlt
Copy link

pohlt commented Feb 11, 2021

Same issue here for me (await browser.close() hangs):

  • Chrome Version 88.0.4324.150 (Official Build) (64-bit)
  • Python playwright 1.8.0.a1
  • non-headless
  • Windows 10 Prof (64-bit) 1909

@tommulkins
Copy link

I had the same problem until I downgraded to Playwright v1.6.0. That seems to work with Chrome binary on Mac OS and closes a headfull browser.

@jonny7
Copy link

jonny7 commented May 14, 2021

I also have this with v1.11.0 with headfull, note headless is fine. This is the setup.ts file for my suites:

import { Browser, chromium, Page } from "playwright";

let browser: Browser;
let page: Page

before(async () => {
  browser = await chromium.launch({ headless: false });
});

after(async () => {
  await browser.close();
});

beforeEach(async () => {
  page = await browser.newPage();
});

afterEach(async () => {
  await page.close();
});

export { page, browser }

@delimmy
Copy link

delimmy commented May 22, 2021

+1 same issue with headful on v1.11.0. Process just hangs forever even with calling browser.close(); This should be considered a major bug that impacts all headful workflows imo.

@delimmy
Copy link

delimmy commented May 22, 2021

This is happening when I'm using the "chrome" stable channel (so it launches real Chrome), but I'm not seeing the issue with Chromium.

@delimmy
Copy link

delimmy commented May 22, 2021

Actually, I wasn't closing the browser properly, but it is still odd that the process hangs on chrome stable but not when "channel" is not specified when launching the browser.

@mailtogagan
Copy link

I also observed the same issue with Playwright 1.12.3, and Chrome 91.0.44.72.101 (32 bit).
Test execution was fast but it looks like browser closure is taking ages before forcefully killing it.

pw:api => browserContext.close started +1ms
  pw:api <= browserContext.close succeeded +40ms
  pw:api => browser.close started +16ms
  pw:browser [pid=54900] <gracefully close start> +3s
  pw:browser [pid=54900] <kill> +30s
  pw:browser [pid=54900] <will force kill> +1ms
  pw:browser [pid=54900] taskkill output: SUCCESS: The process with PID 53636 (child process of PID 54900) has been terminated.
  pw:browser SUCCESS: The process with PID 54480 (child process of PID 54900) has been terminated.
  pw:browser SUCCESS: The process with PID 56632 (child process of PID 54900) has been terminated.
  pw:browser SUCCESS: The process with PID 11660 (child process of PID 54900) has been terminated.
  pw:browser SUCCESS: The process with PID 54480 (child process of PID 54900) has been terminated.
  pw:browser SUCCESS: The process with PID 54900 (child process of PID 54996) has been terminated.
  pw:browser +516ms
  pw:browser [pid=13148] starting temporary directories cleanup +0ms
  
  1 passed(37s)

@ducalpha
Copy link

ducalpha commented Oct 3, 2021

I got the same problem on Playwright Python 1.15.2. The browser context close() hanged when the context was launched in the headful mode by browser_type.launch_persistent_context() with a record_har_path to record a HAR archive. The context closed normally without the record_har_path (set to None).
A workaround is to open a new tab, then close all other tabs, then close the browser context.

@TimurNurlygayanov
Copy link

I have the same issue with Playwright 1.19.2 (TypeScript), when I enable channel: "chrome", the tests are failing because browser.close() "hangs" and playwright is not able to start new browser for next test scenario.

@NickDuBois
Copy link

NickDuBois commented Apr 29, 2022

We are experiencing the same issues. Locally and within a Github Action.

Node: 14.18.2
playwright/test: 1.21.1
Ubuntu 20.04
I believe this is both Chrome & Firefox.

In Headless: False mode. I can see a browser not close and remain open until the suite complete and all closes as expected.

In headless: True the workflow completes what it can per set workers/browsers, and then when all else is done, the workflow just sits there.

In github, when I cancel to workflow/test, in the post clean up output I see something like this:

Cleaning up orphan processes
Terminate orphan process: pid (10634) (sh)
Terminate orphan process: pid (10647) (node)
Terminate orphan process: pid (10659) (sh)
Terminate orphan process: pid (10660) (node)
Terminate orphan process: pid (10689) (node)
Terminate orphan process: pid (13358) (firefox)
Terminate orphan process: pid (14095) (WebExtensions)

This is what leads me to believe this is also a firefox issue.

@beloquintana
Copy link

I have the same issue with chromium. I am using:

  • CucumberJs
  • "@playwright/test": "1.26.0" (TypeScript)
  • headless = false

The browser.close(); takes too long.

@akhilputhiry
Copy link

akhilputhiry commented Dec 16, 2022

Facing same issue. browser is not closing and test timesout.
For me if I remove recordHar it works properly

@aandrzejczuk
Copy link

I have the same issue with chromium browser chrome channel (no issue for msedge). I am using:

  • Playwright Version: 1.35.0
  • Operating System: Windows 11 Enterprise (no issue in linux docker container for dotnet playwright)
  • .NET version: 6.0
  • Browser: Chrome (version 114.0.5735.199)
  • Headless: false and also "--headless=new" (no issue for "--headless=old" option)

await IBrowser.CloseAsync() takes 30 seconds and then times out.

Attaching logs for pw:protocol and pw:browser
mylog_protocol.txt

@mohsen1
Copy link

mohsen1 commented Aug 23, 2023

This is still happening for all Chromium based browser macOS:

My setup:

  • macOS: 13.5 (22G74)
  • Node.js 20
  • "@playwright/test": "^1.37.0"
  • Worth noting that my Chrome is managed by Chrome Enterprise

I'm running the following script:

example.js
const { chromium, webkit, firefox } = require('@playwright/test');

async function main() {
  const msedge = await chromium.launch({
    channel: 'msedge',
    headless: false,
  });
  console.log('\n\n*** MS Edge ***');
  await test(msedge);

  const chrome = await chromium.launch({
    channel: 'chrome',
    headless: false,
  });
  console.log('\n\n*** Chrome ***');
  await test(chrome);

  const chromiumBrowser = await chromium.launch({
    channel: 'chrome',
    headless: false,
  });
  console.log('\n\n*** Chromium ***');
  await test(chromiumBrowser);

  const webkitBrowser = await webkit.launch({
    headless: false,
  });
  console.log('\n\n*** Webkit ***');
  await test(webkitBrowser);

  const firefoxBrowser = await firefox.launch({
    headless: false,
  });
  console.log('\n\n*** Firefox ***');
  await test(firefoxBrowser);
}

async function test(browser) {
  const context = await browser.newContext();
  const page = await context.newPage();

  console.log(new Date().toLocaleTimeString(), 'Navigating to https://example.com');
  await page.goto('https://example.com', { waitUntil: 'load' });

  console.log(new Date().toLocaleTimeString(), 'Closing browser...');
  console.time('Closing browser took');
  await browser.close();
  console.timeEnd('Closing browser took');
}

process.on('unhandledRejection', (reason, promise) => {
  console.log('Unhandled Rejection at:', reason.stack || reason);
});

process.on('uncaughtException', (error) => {
  console.log('Uncaught Exception thrown', error);
});

process.on('exit', (code) => {
  console.log(new Date().toLocaleTimeString(), `About to exit with code: ${code}`);
});

main()
  .then(() => {
    console.log(new Date().toLocaleTimeString(), 'Script finished');
  })
  .catch((err) => {
    console.error('Error during playwright script', err);
  });

I'm getting the following output:

*** MS Edge ***
1:51:03 PM Navigating to https://example.com
1:51:12 PM Closing browser...
Closing browser took: 30.035s


*** Chrome ***
1:51:43 PM Navigating to https://example.com
1:51:44 PM Closing browser...
Closing browser took: 30.068s


*** Chromium ***
1:52:14 PM Navigating to https://example.com
1:52:15 PM Closing browser...
Closing browser took: 30.048s


*** Webkit ***
1:52:46 PM Navigating to https://example.com
1:52:46 PM Closing browser...
Closing browser took: 18.404ms


*** Firefox ***
1:52:48 PM Navigating to https://example.com
1:52:48 PM Closing browser...
Closing browser took: 2.054s
1:52:50 PM Script finished
1:52:50 PM About to exit with code: 0

Closing a Chromium browser takes exactly 30 seconds! There must be a timeout somewhere...
Other browsers (Firefox and Webkit) are working correctly.

context.close does not help

Closing all contexts before browser.close() does not fix the issue:

  const contexts = await browser.contexts();
  await Promise.all(contexts.map((ctx) => ctx.close()));
  await browser.close();

@dgozman
Copy link
Contributor

dgozman commented Aug 23, 2023

@mohsen1 Enterprise policies may interfere with Playwright controlling the browser. We consider this case to be out of scope, so it's unlikely things will improve in this area.

@mohsen1
Copy link

mohsen1 commented Aug 23, 2023

Thank you @dgozman, in a Mac without Chrome Enterprise the close times are around 2 seconds. It's surprising that Chrome Enterprise is impacting all of Chromium based browsers. I understand that this is outside of the scope of Playwright but do you have any suggestions where can I look for possible solutions?

@dgozman
Copy link
Contributor

dgozman commented Aug 23, 2023

@mohsen1 There is no known workaround, except for using Playwright's built-in chromium and not passing channel.

@mohsen1
Copy link

mohsen1 commented Aug 23, 2023

In our case, Chromium (without the channel specified) also takes 30 seconds to close.

@dgozman
Copy link
Contributor

dgozman commented Aug 24, 2023

@mohsen1 This is interesting. Could you please run with DEBUG=pw:browser* environment variable and share the logs?

@mohsen1
Copy link

mohsen1 commented Aug 24, 2023

Updated the script to remove channel from Chromium

const { chromium, webkit, firefox } = require('@playwright/test');

async function main() {
  const msedge = await chromium.launch({
    channel: 'msedge',
    headless: false,
  });
  console.log('\n\n*** MS Edge ***');
  await test(msedge);

  const chrome = await chromium.launch({
    channel: 'chrome',
    headless: false,
  });
  console.log('\n\n*** Chrome ***');
  await test(chrome);

  const chromiumBrowser = await chromium.launch({
    headless: false,
  });
  console.log('\n\n*** Chromium ***');
  await test(chromiumBrowser);

  const webkitBrowser = await webkit.launch({
    headless: false,
  });
  console.log('\n\n*** Webkit ***');
  await test(webkitBrowser);

  const firefoxBrowser = await firefox.launch({
    headless: false,
  });
  console.log('\n\n*** Firefox ***');
  await test(firefoxBrowser);
}

async function test(browser) {
  const context = await browser.newContext();
  const page = await context.newPage();

  console.log(new Date().toLocaleTimeString(), 'Navigating to https://example.com');
  await page.goto('https://example.com', { waitUntil: 'load' });

  console.log(new Date().toLocaleTimeString(), 'Closing browser...');
  console.time('Closing browser took');
  await browser.close();
  console.timeEnd('Closing browser took');
}

process.on('unhandledRejection', (reason, promise) => {
  console.log('Unhandled Rejection at:', reason.stack || reason);
});

process.on('uncaughtException', (error) => {
  console.log('Uncaught Exception thrown', error);
});

process.on('exit', (code) => {
  console.log(new Date().toLocaleTimeString(), `About to exit with code: ${code}`);
});

main()
  .then(() => {
    console.log(new Date().toLocaleTimeString(), 'Script finished');
  })
  .catch((err) => {
    console.error('Error during playwright script', err);
  });

Command: DEBUG=pw:browser* DEBUG_FILE=pw.log node pw.js

Output:


*** MS Edge ***
5:46:15 PM Navigating to https://example.com
5:46:17 PM Closing browser...
Closing browser took: 30.056s


*** Chrome ***
5:46:47 PM Navigating to https://example.com
5:46:48 PM Closing browser...
Closing browser took: 30.048s


*** Chromium ***
5:47:21 PM Navigating to https://example.com
5:47:21 PM Closing browser...
Closing browser took: 30.048s


*** Webkit ***
5:47:55 PM Navigating to https://example.com
5:47:56 PM Closing browser...
Closing browser took: 17.823ms


*** Firefox ***
5:47:58 PM Navigating to https://example.com
5:47:58 PM Closing browser...
Closing browser took: 1.931s
5:48:00 PM Script finished
5:48:00 PM About to exit with code: 0

I did not see any content in my pw.log file. Not sure what I'm doing wrong?

@dgozman
Copy link
Contributor

dgozman commented Aug 24, 2023

I did not see any content in my pw.log file. Not sure what I'm doing wrong?

I am not sure. After running your command on my computer, I got pw.log file with some logs.

@kaliiiiiiiiii
Copy link

kaliiiiiiiiii commented Oct 9, 2023

Something like:

async function close(endpoint) {
    let promise
    const ws = new WebSocket(endpoint);
    ws.on('open', function open() {
        ws.send("{'id': 0, 'method': 'Browser.close', 'params':{}");
        ws.close()
        promise = Promise.resolve()
    });
    return await promise
}
const server  = await chromium.launchServer({
        headless: false,
        executablePath: "C:/Program Files/Google/Chrome/Application/chrome.exe",
    })
endpoint = server.wsEndpoint()
await close(endpoint) // patches https://github.com/microsoft/playwright/issues/5327

however raises the following after closing

>SyntaxError: Unexpected token ' in JSON at position 1
 >    at JSON.parse (<anonymous>)
 >    at i.<anonymous> (C:\Users\aurin\source\repos\playwright test\playwright test\node_modules\playwright-core\lib\remote\playwrightConnection.js:65:48)
 >    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

( not sure how to catch that error)

jingyin pushed a commit to PathOnAI/LiteWebAgent that referenced this issue Aug 2, 2024
applies the close hook on a page to persist state of the context
before quitting. doesn't work on chromium for now due to a known issue
with how `browser.close()` doesn't work

microsoft/playwright#5327
jingyin added a commit to PathOnAI/LiteWebAgent that referenced this issue Aug 2, 2024
applies the close hook on a page to persist state of the context
before quitting. doesn't work on chromium for now due to a known issue
with how `browser.close()` doesn't work

microsoft/playwright#5327
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests