[FFmpeg-devel] TCP socket descriptor leak on listen and interrupt

Stephan Holljes klaxa1337 at googlemail.com
Fri Sep 11 21:27:11 CEST 2015


On Fri, Sep 11, 2015 at 8:48 AM, Alexander Drozdov <adrozdoff at gmail.com> wrote:
> Hi all!
>
> We are found another descriptors leak :-)
>
> If we try to listen on TCP port and ff_listen() fails on
> interrupt callback, socket (bind) descriptor overwrites at the tcp_open()
> and does not closed at all.
>
> As a result, we can't rebind to the same port.
>
> Minimal sample for issue (sorry for C++ in some places :-), also sample
> code assumes that librtmp does not used - it does not allow to listen):
> ```
> #include <iostream>
> #include <unistd.h>
>
> extern "C" {
>   #ifndef __STDC_CONSTANT_MACROS
>   #define __STDC_CONSTANT_MACROS
>   #endif
>
>   #include <libavcodec/avcodec.h>
>   #include <libavformat/avformat.h>
>   #include <libavfilter/avfilter.h>
>   #include <libswscale/swscale.h>
>   #include <libavdevice/avdevice.h>
>   #include <libswresample/swresample.h>
>   #include <libavutil/log.h>
> }
>
> int openInputInterruptCallBack(void *ctx)
> {
>     // I know, stupid code :-) in real code more complex logic here
>     return 1;
> }
>
> int main(int argc, char **argv) {
>     std::cout << "Hello, world!" << std::endl;
>
>     avdevice_register_all();
>     avcodec_register_all();
>     avfilter_register_all();
>     av_register_all();
>     avformat_network_init();
>
>     AVFormatContext *mpFormatCtx = avformat_alloc_context();
>     mpFormatCtx->interrupt_callback.callback = &openInputInterruptCallBack;
>     mpFormatCtx->interrupt_callback.opaque   = mpFormatCtx;
>
>     AVDictionary * dict = nullptr;
>     av_dict_set_int(&dict, "rtmp_listen", 1, 0);
>     av_dict_set_int(&dict, "timeout", -1, 0);
>     av_dict_set(&dict, "rtmp_live", "live", 0);
>     char* inputFileName = "rtmp://0.0.0.0:1936/live/mystream";
>     AVInputFormat *pInAvFormat = av_find_input_format(inputFileName);
>
>     int err = avformat_open_input(&mpFormatCtx, inputFileName, pInAvFormat,
> &dict);
>     // avformat_open_input() fails here but bind socket descriptor still
> open.
>     // we can check it via `ls -l /proc/PID/fd`
>
>     if(err != 0)  {
>         char errMsg[100];
>         av_strerror(err, errMsg, 100);
>         std::cout << "Couldn't open input source: " << inputFileName <<",
> err : " << errMsg << std::endl;
>         avformat_network_deinit();
>
>         for (;;)
>             sleep(1);
>
>         return -1;
>     } else {
>         avformat_close_input(&mpFormatCtx);
>         avformat_network_deinit();
>     }
>
>     return 0;
> }
> ```
>
> Fix is attached to the letter.
>
> --
> WBR, Alexander Drozdov
> http://htrd.su
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

I worked on this code and patch LGTM. I can follow where and how the
filedescriptor is lost/leaked.
Minor thing: the second line of the if-clause should line up with the
parenthesis.

Regards,
Stephan


More information about the ffmpeg-devel mailing list