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-inside-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 \ + sigset_t oldset, newset; \ + siginfo_t si; \ + struct timespec ts = {0}; \ + 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; } -- 2.1.4 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel