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?

> +    sigset_t oldset, newset; \
> +    siginfo_t si; \
> +    struct timespec ts = {0}; \

0,0 to avoid a warning?

> +    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;
>  }

-- 
Rémi Denis-Courmont
Remlab T:mi
http://www.remlab.net/

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to