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