Skip to content

When index method is called in recursion it kills python interpreter #1602

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

Closed
hmilkovi opened this issue Jun 4, 2021 · 2 comments
Closed

Comments

@hmilkovi
Copy link
Contributor

hmilkovi commented Jun 4, 2021

Hi all,

Versions:

  • elasticsearch==7.13.0
  • Python 3.8.6

Expected:

  • Raise any kind of error

Behavior:

  • Fatal Python error: Cannot recover from stack overflow.
  • Doesn't respect sys.getrecursionlimit() and gets called ~1029 in test case 1000 is the recursion limit

To reproduce:

import os
import sys
import inspect
import elasticsearch

es_client = elasticsearch.Elasticsearch(
    [os.environ["ELASTIC_API"]],
    verify_certs=False,
)
print(sys.getrecursionlimit())
def rec():
    print(len(inspect.stack()))
    es_client.index(index='testing', body={'test': 'test'}, request_timeout=1)
    rec()

rec()
@sethmlarson
Copy link
Contributor

sethmlarson commented Jun 4, 2021

I'm not sure there's much we can do here, the function itself is infinitely recursive so of course you're going to hit the recursion limit eventually? What are we supposed to fix here?

Going to close this for now, let me know if there's something we can do.

@hmilkovi
Copy link
Contributor Author

hmilkovi commented Jun 4, 2021

Hi @sethmlarson, one thing is exception (hiting the limit) RecursionError is not the case, the case is core dump and whole interpreter trashes (going over the limit and then core dump).

Use case where we in recursion to index 2000 documents -> won't work.

Also issue is similar to this one that was solved: https://bugs.python.org/issue36272

I have fixed it in my code with:

if len(inspect.stack()) >= sys.getrecursionlimit():
            raise RecursionError

The issue is that https://github.com/elastic/elasticsearch-py/blob/master/elasticsearch/connection/http_urllib3.py#L256 RecursionError it doesn't get propagated it's needed to be.

In python recursion and even change it's limit like:
sys.setrecursionlimit(Newlimit)
and here it get's interesting as it'd doesn't core dump until it exceeds Pythons recursion limit.

Tested cases:

  1. When left default limit (1000) it crashes on 1029
  2. When I set limit to 1500 it crashes on 1529
  3. When I set limit to 2 it doesn't crash interpreter and returns expected RecursionError
  4. When I set it to 100 it crashes on 129

Please consider my PR: #1607

Recursion limit before: 1000
Recursion limit After: 100
2
3
....
126
127
128
129
Fatal Python error: Cannot recover from stack overflow.
Python runtime state: initialized

Current thread 0x00007f0848578740 (most recent call first):
  File "/usr/lib/python3.8/email/utils.py", line 57 in _has_surrogates
  File "/usr/lib/python3.8/email/_policybase.py", line 287 in _sanitize_header
  File "/usr/lib/python3.8/email/_policybase.py", line 316 in header_fetch_parse
  File "/usr/lib/python3.8/email/message.py", line 471 in get
  File "/usr/lib/python3.8/email/message.py", line 578 in get_content_type
  File "/usr/lib/python3.8/email/message.py", line 594 in get_content_maintype
  File "/usr/lib/python3.8/email/feedparser.py", line 295 in _parsegen
  File "/usr/lib/python3.8/email/feedparser.py", line 180 in _call_parse
  File "/usr/lib/python3.8/email/feedparser.py", line 176 in feed
  File "/usr/lib/python3.8/email/parser.py", line 56 in parse
  File "/usr/lib/python3.8/email/parser.py", line 67 in parsestr
  File "/usr/lib/python3.8/http/client.py", line 225 in parse_headers
  File "/usr/lib/python3.8/http/client.py", line 331 in begin
  File "/usr/lib/python3.8/http/client.py", line 1347 in getresponse
  File "<redacted>/venv/lib/python3.8/site-packages/urllib3/connectionpool.py", line 440 in _make_request
  File "<redacted>/venv/lib/python3.8/site-packages/urllib3/connectionpool.py", line 699 in urlopen
  File "<redacted>/venv/lib/python3.8/site-packages/elasticsearch/connection/http_urllib3.py", line 251 in perform_request
  File "<redacted>/venv/lib/python3.8/site-packages/elasticsearch/transport.py", line 381 in perform_request
  File "<redacted>/venv/lib/python3.8/site-packages/elasticsearch/client/__init__.py", line 406 in index
  File "<redacted>/venv/lib/python3.8/site-packages/elasticsearch/client/utils.py", line 168 in _wrapped

Code:

import os
import sys
import inspect
import elasticsearch
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

es_client = elasticsearch.Elasticsearch(
    [os.environ["ELASTIC_API"]],
    verify_certs=False,
)
print(f"Recursion limit before: {sys.getrecursionlimit()}")
sys.setrecursionlimit(100)
print(f"Recursion limit After: {sys.getrecursionlimit()}")
def rec():
    print(len(inspect.stack()))
    es_client.index(index='testing', body={'test': 'test'}, request_timeout=1)
    rec()

rec()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants