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