[Home]

Summary:ASTERISK-28765: tcptls API: bad file descriptor when connection fails
Reporter:Jean Aunis - Prescom (PrescomJA)Labels:
Date Opened:2020-03-03 05:18:45.000-0600Date Closed:2020-09-30 12:40:07
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Applications/app_externalivr Channels/chan_sip/TCP-TLS
Versions:16.3.0 Frequency of
Occurrence
Constant
Related
Issues:
duplicatesASTERISK-28430 res_rtp_asterisk.c: FRACK!, Failed assertion errno != EBADF
Environment:Attachments:
Description:When trying to connect to an ExternalIVR() which is not started, a "Bad file descriptor" error is reported.

Excerpt from the logs:
{code}
-- Executing [2000@default:1] ExternalIVR("Local/2000@default-00000000;2", "ivr://127.0.0.1") in new stack
   -- Called 2000@default
      > ExternalIVR received application and arguments: ivr://127.0.0.1
      > ExternalIVR received options: (null)
      > Parsing options from: [(null)]
   -- Answering channel and starting generator
   -- Local/2000@default-00000000;1 answered
      > Launching Wait(1000) on Local/2000@default-00000000;1
[Mar  3 11:58:57] ERROR[16427][C-00000001]: tcptls.c:553 ast_tcptls_client_start: Unable to connect IVR to 127.0.0.1:2949: Connection refused
[Mar  3 11:58:57] ERROR[16427][C-00000001]: iostream.c:569 ast_iostream_close: close() failed: Bad file descriptor
[Mar  3 11:58:57] ERROR[16427][C-00000001]: app_externalivr.c:529 app_exec: Local/2000@default-00000000;2: Could not connect to any host.  ExternalIVR failed.
{code}

A similar issue happens when using chan_sip with TCP transport.

It seems that ast_tcptls_client_start closes twice the same file descriptor.
It can randomly affect Asterisk stability if the same file descriptor is reused in the meantime.
Comments:By: Asterisk Team (asteriskteam) 2020-03-03 05:18:46.825-0600

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

Please note that once your issue enters an open state it has been accepted. As Asterisk is an open source project there is no guarantee or timeframe on when your issue will be looked into. If you need expedient resolution you will need to find and pay a suitable developer. Asking for an update on your issue will not yield any progress on it and will not result in a response. All updates are posted to the issue when they occur.

By: Kevin Harwell (kharwell) 2020-03-03 13:57:14.429-0600

Yep, trying to close it twice. It appears when creating the client both the tcptls session and underlying stream take "ownership" of the socket. See [here|https://github.com/asterisk/asterisk/blob/master/main/tcptls.c#L638] in _ast_tcptls_client_create_:
{noformat}
fd = desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ?
     AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
{noformat}
And then a [bit further down|https://github.com/asterisk/asterisk/blob/master/main/tcptls.c#L670] when the stream is created:
{noformat}
tcptls_session->stream = ast_iostream_from_fd(&fd);
{noformat}
[_ast_iostream_from_fd_|https://github.com/asterisk/asterisk/blob/master/main/iostream.c#L604] copies the file descriptor, and resets the given one. However the given one is a pointer to a stack variable and not the one "owned" by the parent session:
{noformat}
if (stream) {
stream->timeout = -1;
stream->timeout_reset = -1;
stream->fd = *fd;
*fd = -1;
}
{noformat}
It might be all one has to do is pass in the parent file descriptor when creating the stream instead, but further investigation needs to be done into the possible side effects of doing that.