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

Michael Niedermayer michaelni at gmx.at
Fri Sep 11 22:01:09 CEST 2015


On Fri, Sep 11, 2015 at 09:27:11PM +0200, Stephan Holljes wrote:
> 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.

fixed

applied

thanks

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150911/93fbaec4/attachment.sig>


More information about the ffmpeg-devel mailing list