twilio / twilio-python

A Python module for communicating with the Twilio API and generating TwiML.
MIT License
1.86k stars 710 forks source link

ResourceWarning: unclosed ssl socket #585

Closed jpodpro closed 2 years ago

jpodpro commented 2 years ago

Issue Summary

When using client.calls.create to send a voice message i get an unclosed ssl socket ResourceWarning. The call and translation works fine.

UPDATE: this doesn't happen immediatey on the first run - i have to wait 20 seconds or so. however subsequent calls to the code without restarting the server result in the given ResourceWarning error instantly.

Code Snippet

message = 'shubbit yo face'
client = Client() if is_production else Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
client_call = client.calls.create(
    status_callback=twilio_status_callback_url_builder(),
    status_callback_event=['initiated', 'ringing', 'answered', 'completed'],
    status_callback_method='POST',
    to="+1{0}".format(phone_number),
    from_=settings.TWILIO_PHONE_NUMBER,
    url=twilio_voice_callback_url_builder({
        'say': json.dumps(message)
    })
)

Exception/Log

C:\<hidden>\Python\Python39\lib\pathlib.py:189: ResourceWarning: unclosed <ssl.SSLSocket fd=1636, f
amily=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('<hidden>', 52915), raddr=('<hidden>', 443)>
  return [p.lower() for p in parts]
ResourceWarning: Enable tracemalloc to get the object allocation traceback
sys:1: ResourceWarning: unclosed <ssl.SSLSocket fd=1756, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, la
ddr=('<hidden>', 52913), raddr=('<hidden>', 443)>
ResourceWarning: Enable tracemalloc to get the object allocation traceback

Technical details:

jpodpro commented 2 years ago

after much research it seems like this is a consequence of pooling / reusing connections. i found someone else with the same issue using a google api client. if this is the case perhaps some documentation about it would be helpful as i have spent quite a bit of time researching and digging through the api code to find a proper way to deal with this. for now i am simply using warnings.simplefilter("ignore", ResourceWarning) to ignore it.

eshanholtz commented 2 years ago

Hi @jpodpro

We actually have the ability to override the pooling connections behavior built-in! To do this, you will need to pass in a Custom HTTP Client that has the pool_connections flag turned off. For example:

import os
from twilio.rest import Client
from twilio.http.http_client import TwilioHttpClient

# Override default pooling behavior
custom_http_client = TwilioHttpClient(pool_connections=False)

client = Client(os.getenv("ACCOUNT_SID"), os.getenv("AUTH_TOKEN"),
                http_client=custom_http_client)

message = client.messages \
    .create(
        to="+15558675310",
        body="Hey there!",
        from_="+15017122661"
    )

print('Message SID: {}'.format(message.sid))
eshanholtz commented 2 years ago

Closing due to lack of customer response. Hope it worked!

tamird commented 7 months ago

I am still seeing this. It is caused by the fact that the passed-in http client is never closed, and there's no way to close it from the outside.

The client is retained here, but is not exposed, so it can never be closed.

Disabling connection pooling is not the right solution.