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

HTTP2 support rarely breaks #1164

Closed
2 tasks done
fengkx opened this issue Apr 20, 2020 · 9 comments
Closed
2 tasks done

HTTP2 support rarely breaks #1164

fengkx opened this issue Apr 20, 2020 · 9 comments
Assignees
Labels
bug Something does not work as it should external The issue related to an external project

Comments

@fengkx
Copy link
Contributor

fengkx commented Apr 20, 2020

Describe the bug

  • Node.js version: 12.16.1 & 13.13.0
  • OS & version: Linux 5.5.18-1-MANJARO

Actual behavior

/home/fengkx/demos/got-error/node_modules/http2-wrapper/source/agent.js:111
        for (const session of where[name]) {
                                   ^

TypeError: where[name] is not iterable
    at closeSessionIfCovered (/home/fengkx/demos/got-error/node_modules/http2-wrapper/source/agent.js:111:29)
    at ClientHttp2Stream.<anonymous> (/home/fengkx/demos/got-error/node_modules/http2-wrapper/source/agent.js:524:9)
    at Object.onceWrapper (events.js:417:28)
    at ClientHttp2Stream.emit (events.js:323:22)
    at emitCloseNT (internal/streams/destroy.js:69:8)
    at processTicksAndRejections (internal/process/task_queues.js:83:21)

Get TypeError

Expected behavior

Get a HTTPError or RequestError

Code to reproduce

const got = require('got');
const pMap = require('p-map');

(async () => {
        const url = 'https://httpbin.org/status/404';
        const urls = Array(200).fill(url);
        const statusCodes = await pMap(urls, async url => {
                try {
                        const resp = await got(url, {http2: true}); // always 404 HTTPError
                        return resp.statusCode;
                } catch(e) {
                        return e.name;
                }
        }, {cocurrency: 25});
        console.log(statusCodes)
})();

I can get Error back when http2 options is false.


I also get a error when I enable http2 in production. But I cannot reproduce it with a few lines of code now.

error: https://rsshub.app/zhihu/hotlist HTTPError: Response code 404 (Not Found)
    at PromisableRequest.<anonymous> (/root/NodeRSSBot/node_modules/got/dist/source/as-promise/index.js:122:28)
    at processTicksAndRejections (internal/process/task_queues.js:85:5) {"timestamp":"2020-04-20T18:32:59.103Z"}
events.js:186
      throw er; // Unhandled 'error' event
      ^

Error: 140328935499648:error:14094123:SSL routines:ssl3_read_bytes:application data after close notify:../deps/openssl/openssl/ssl/record/rec_layer_s3.c:1600:

Emitted 'error' event on TLSSocket instance at:
    at TLSSocket._emitTLSError (_tls_wrap.js:748:10)
    at TLSWrap.onerror (_tls_wrap.js:330:11) {
  library: 'SSL routines',
  function: 'ssl3_read_bytes',
  reason: 'application data after close notify',
  code: 'ERR_SSL_APPLICATION_DATA_AFTER_CLOSE_NOTIFY'
}

It is when I request multi-sites at the same times and many of them will rise HTTPError, then it will rise an uncaughtException
Temporary set http2 option to false fix it.

Checklist

  • I have read the documentation.
  • I have tried my code with the latest version of Node.js and Got.
@szmarczak
Copy link
Collaborator

Thanks for reporting, I'll look at this ASAP.

@szmarczak szmarczak added bug Something does not work as it should external The issue related to an external project labels Apr 20, 2020
@szmarczak szmarczak self-assigned this Apr 20, 2020
@szmarczak szmarczak changed the title TypeError when many request throw Error at the same time using http2 HTTP2 support is partially broken Apr 20, 2020
@szmarczak
Copy link
Collaborator

TypeError: where[name] is not iterable seems to be caused by a race condition.
The SSL error is likely to be a bug in the Node.js core.

It is when I request multi-sites at the same times and many of them will rise HTTPError, then it will rise an uncaughtException

I'll test that.

@szmarczak
Copy link
Collaborator

szmarczak commented Apr 20, 2020

TypeError: where[name] is not iterable happens when there are no free HTTP2 sessions and the current session is busy (you cannot use it to make requests anymore). I overlooked this scenario.

It is easily fixable by putting the closeSessionIfCovered(...) in

if (this.freeSessions[normalizedOptions]) {
	// closeSessionIfCovered(...)
}

I'll fix this tomorrow.

--
A note to myself (http2-wrapper): should _destroy utilize the callback fn it has as a second argument?

@szmarczak
Copy link
Collaborator

You made a typo in your code:

cocurrency -> concurrency

@szmarczak szmarczak changed the title HTTP2 support is partially broken HTTP2 support rarely breaks Apr 20, 2020
@szmarczak
Copy link
Collaborator

Your bug led me into another bugs in the http2-wrapper module. Gonna fix this tomorrow, need to get some sleep now.

@szmarczak
Copy link
Collaborator

Good news: I can reproduce the TypeError: where[name] is not iterable error.

@szmarczak
Copy link
Collaborator

Fixed in the http2-wrapper package, will do a release soon.

@szmarczak
Copy link
Collaborator

It is when I request multi-sites at the same times and many of them will rise HTTPError, then it will rise an uncaughtException

What uncaughtException are you talking about? The SSL error?

@fengkx
Copy link
Contributor Author

fengkx commented Apr 21, 2020

What uncaughtException are you talking about? The SSL error?

Yes, The SSL error I think. I notice the comment in https://github.com/nodejs/node/blob/v13.8.0/lib/events.js#L182

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something does not work as it should external The issue related to an external project
Projects
None yet
Development

No branches or pull requests

2 participants