On Sun, 10 May 2015 20:38:09 +0300
Rémi Denis-Courmont <r...@remlab.net> wrote:

> Le dimanche 10 mai 2015, 19:15:25 wm4 a écrit :
> > A low-effort fix for fixing SIGPIPE being raised in some situations
> > because OpenSSL uses a naive write() to send data to the socket without
> > using MSG_NOSIGNAL.
> > 
> > The idea and code for blocking and unqueuing SIGPIPE is taken from:
> > http://stackoverflow.com/questions/24920748/how-to-handle-a-sigpipe-error-in
> > side-the-object-that-generated-it/24921005#24921005
> > 
> > A proper fix would probably either fix OpenSSL itself, or use a callback
> > based BIO wrapper.
> > ---
> > I'm very sorry for even sending this shitty patch.
> > 
> > My hope is that someone else implements a proper fix, because I'm too
> > lazy to write a proper fix. (Matching OpenSSL's and avio's IO doesn't
> > sound like fun.)
> > ---
> >  libavformat/tls.c | 41 +++++++++++++++++++++++++++++++++++------
> >  1 file changed, 35 insertions(+), 6 deletions(-)
> > 
> > diff --git a/libavformat/tls.c b/libavformat/tls.c
> > index 4a52e84..892fa6f 100644
> > --- a/libavformat/tls.c
> > +++ b/libavformat/tls.c
> > @@ -57,6 +57,25 @@
> >  #include <poll.h>
> >  #endif
> > 
> > +#if CONFIG_OPENSSL && HAVE_POLL_H && HAVE_PTHREADS
> > +#include <pthread.h>
> > +#include <signal.h>
> > +#include <errno.h>
> > +#define BLOCK_SIGPIPE \
> 
> Why an ugly macro rather than two function calls?

It requires at least remembering the previous signal state (the oldset
variable). Since sigset_t is not necessarily always available (win32,
OS/2 at least), I thought it wouldn't make much of a difference whether
an ugly macro or an ugly macro is used.

> > +    sigset_t oldset, newset; \
> > +    siginfo_t si; \
> > +    struct timespec ts = {0}; \
> 
> 0,0 to avoid a warning?

Well, {0} is basically the standard way to zero-initialize anything,
and is always valid. If the compiler warns, it's IMHO a compiler
deficiency.

> > +    sigemptyset(&newset); \
> > +    sigaddset(&newset, SIGPIPE); \
> > +    pthread_sigmask(SIG_BLOCK, &newset, &oldset);
> > +#define UNBLOCK_SIGPIPE \
> > +    while (sigtimedwait(&newset, &si, &ts) >= 0 || errno != EAGAIN) {}; \
> > +    pthread_sigmask(SIG_SETMASK, &oldset, 0);
> > +#else
> > +#define BLOCK_SIGPIPE
> > +#define UNBLOCK_SIGPIPE
> > +#endif
> > +
> >  typedef struct TLSContext {
> >      const AVClass *class;
> >      URLContext *tcp;
> > @@ -155,6 +174,7 @@ static int tls_open(URLContext *h, const char *uri, int
> > flags, AVDictionary **op struct addrinfo hints = { 0 }, *ai = NULL;
> >      const char *proxy_path;
> >      int use_proxy;
> > +    BLOCK_SIGPIPE
> > 
> >      ff_tls_init();
> > 
> > @@ -317,12 +337,14 @@ static int tls_open(URLContext *h, const char *uri,
> > int flags, AVDictionary **op goto fail;
> >      }
> >  #endif
> > +    UNBLOCK_SIGPIPE
> >      return 0;
> >  fail:
> >      TLS_free(c);
> >      if (c->tcp)
> >          ffurl_close(c->tcp);
> >      ff_tls_deinit();
> > +    UNBLOCK_SIGPIPE
> >      return ret;
> >  }
> > 
> > @@ -344,25 +366,32 @@ static int tls_read(URLContext *h, uint8_t *buf, int
> > size) static int tls_write(URLContext *h, const uint8_t *buf, int size) {
> >      TLSContext *c = h->priv_data;
> > +    int ret;
> > +    BLOCK_SIGPIPE
> >      while (1) {
> > -        int ret = TLS_write(c, buf, size);
> > +        ret = TLS_write(c, buf, size);
> >          if (ret > 0)
> > -            return ret;
> > -        if (ret == 0)
> > -            return AVERROR_EOF;
> > +            break;
> > +        if (ret == 0) {
> > +            ret = AVERROR_EOF;
> > +            break;
> > +        }
> >          if ((ret = do_tls_poll(h, ret)) < 0)
> > -            return ret;
> > +            break;
> >      }
> > -    return 0;
> > +    UNBLOCK_SIGPIPE
> > +    return ret;
> >  }
> > 
> >  static int tls_close(URLContext *h)
> >  {
> >      TLSContext *c = h->priv_data;
> > +    BLOCK_SIGPIPE
> >      TLS_shutdown(c);
> >      TLS_free(c);
> >      ffurl_close(c->tcp);
> >      ff_tls_deinit();
> > +    UNBLOCK_SIGPIPE
> >      return 0;
> >  }
> 

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to