49a856cb5c01903c697f866e922c3723cd0d714b
galt
  Tue Mar 1 21:08:09 2016 -0800
Fixes #16872. bigBedToBed on HTTPS URL was terminating with exitcode 141 and being killed by default SIGPIPE behavior. This now has a fairly elegant solution that should work on most OSes.

diff --git src/lib/https.c src/lib/https.c
index 1a8f026..754c05c 100644
--- src/lib/https.c
+++ src/lib/https.c
@@ -1,28 +1,29 @@
 /* Connect via https. */
 
 /* Copyright (C) 2012 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 
 #ifdef USE_SSL
 
 #include "openssl/ssl.h"
 #include "openssl/err.h"
 
 #include <sys/socket.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <signal.h>
 
 #include "common.h"
 #include "internet.h"
 #include "errAbort.h"
 #include "net.h"
 
 
 static pthread_mutex_t *mutexes = NULL;
  
 static unsigned long openssl_id_callback(void)
 {
 return ((unsigned long)pthread_self());
 }
  
 static void openssl_locking_callback(int mode, int n, const char * file, int line)
@@ -270,31 +271,31 @@
 	{
 	/* Timed out - just quit */
 	xerr("https timeout expired");
 	goto cleanup;
 	}
 
     else 
 	{
 	if (FD_ISSET(params->sv[1], &readfds))
 	    {
 	    swt = 0;
 	    srd = read(params->sv[1], sbuf, 32768);
 	    if (srd == -1)
 		{
 		if (errno != 104) // udcCache often closes causing "Connection reset by peer"
-		    xerrno("error reading https socket");
+		    xerrno("error reading user pipe for https socket");
 		goto cleanup;
 		}
 	    if (srd == 0) 
 		break;  // user closed socket, we are done
 	    }
 
 	if (FD_ISSET(fd, &writefds))
 	    {
 	    int swtx = BIO_write(sbio, sbuf+swt, srd-swt);
 	    if (swtx <= 0)
 		{
 		if (!BIO_should_write(sbio))
 		    {
 		    ERR_print_errors_fp(stderr);
 		    xerr("Error writing SSL connection");
@@ -323,36 +324,62 @@
 		    {
 		    brd = 0;
 		    continue;
 		    }
 		else
 		    {
 		    if (brd == 0) break;
 		    ERR_print_errors_fp(stderr);
 		    xerr("Error reading SSL connection");
 		    goto cleanup;
 		    }
 		}
 	    // write the https data received immediately back on socket to user, and it's ok if it blocks.
 	    while(bwt < brd)
 		{
+		// NOTE: Intended as a thread-specific library-safe way not to ignore SIG_PIPE for the entire application.
+		// temporarily block sigpipe on this thread
+		sigset_t sigpipe_mask;
+		sigemptyset(&sigpipe_mask);
+		sigaddset(&sigpipe_mask, SIGPIPE);
+		sigset_t saved_mask;
+		if (pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &saved_mask) == -1) {
+		    perror("pthread_sigmask");
+		    exit(1);
+		}
 		int bwtx = write(params->sv[1], bbuf+bwt, brd-bwt);
+		int saveErrno = errno;
+		if ((bwtx == -1) && (saveErrno == EPIPE))
+		    { // if there was a EPIPE, accept and consume the SIGPIPE now.
+		    struct timespec zerotime = {0};
+		    if (sigtimedwait(&sigpipe_mask, 0, &zerotime) == -1) 
+			{
+			perror("sigtimedwait");
+			exit(1);
+			}
+		    }
+		// restore signal mask on this thread
+		if (pthread_sigmask(SIG_SETMASK, &saved_mask, 0) == -1) 
+		    {
+		    perror("pthread_sigmask");
+		    exit(1);
+		    }
 		if (bwtx == -1)
 		    {
-		    if ((errno != 104)  // udcCache often closes causing "Connection reset by peer"
-		     && (errno !=  32)) // udcCache often closes causing "Broken pipe"
-			xerrno("error writing https data back to user socket");
+		    if ((saveErrno != 104)  // udcCache often closes causing "Connection reset by peer"
+		     && (saveErrno !=  32)) // udcCache often closes causing "Broken pipe"
+			xerrno("error writing https data back to user pipe");
 		    goto cleanup;
 		    }
 		bwt += bwtx;
 		}
 	    brd = 0;
 	    bwt = 0;
 	    }
 	}
     }
 
 cleanup:
 
 BIO_free_all(sbio);
 close(params->sv[1]);  /* we are done with it */
 
@@ -362,30 +389,34 @@
 int netConnectHttps(char *hostName, int port)
 /* Return socket for https connection with server or -1 if error. */
 {
 
 fflush(stdin);
 fflush(stdout);
 fflush(stderr);
 
 struct netConnectHttpsParams *params;
 AllocVar(params);
 params->hostName = cloneString(hostName);
 params->port = port;
 
 socketpair(AF_UNIX, SOCK_STREAM, 0, params->sv);
 
+// netBlockBrokenPipes(); works, but is heavy handed 
+//  and ignores SIGPIPE on all connections for all threads in the entire application. 
+// We are trying something more subtle and library and thread-friendly instead.
+
 int rc;
 rc = pthread_create(&params->thread, NULL, netConnectHttpsThread, (void *)params);
 if (rc)
     {
     errAbort("Unexpected error %d from pthread_create(): %s",rc,strerror(rc));
     }
 
 /* parent */
 
 return params->sv[0];
 
 }
 
 #else