From: Dave H. <hel...@us...> - 2014-05-02 00:02:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "sfcb - Small Footprint CIM Broker". The branch, master has been updated via 5ea194525792471903c0b5f3994fd21618eb348e (commit) from a9dda19abe7356eaeeaaad8be15fabbcb4ff8f29 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5ea194525792471903c0b5f3994fd21618eb348e Author: Dave Heller <hel...@us...> Date: Thu May 1 19:59:43 2014 -0400 [sfcb-tix:#97] Add a select timeout for req handlers ----------------------------------------------------------------------- Summary of changes: control.c | 6 +++++- httpAdapter.c | 14 +++++++++++++- msgqueue.c | 44 +++++++++++++++++++++++++++++++++++++++++--- providerMgr.c | 24 ++++++++++++++++++++++-- sfcb.cfg.pre.in | 12 ++++++++++++ 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/control.c b/control.c index 5c562cf..ed0e5df 100644 --- a/control.c +++ b/control.c @@ -73,9 +73,12 @@ char *ip6List= NULL; char **origArgv; int origArgc; -int useCDATA; unsigned int labelProcs; +int useCDATA; +int httpProcIdX; +long httpReqHandlerTimeout; + /** * Kindly null terminate, always, even if might overwrite * the last char of the truncated string. @@ -158,6 +161,7 @@ static Control init[] = { {"keepaliveMaxRequest", CTL_LONG, NULL, {.slong=10}}, {"selectTimeout", CTL_LONG, NULL, {.slong=5}}, {"maxBindAttempts", CTL_LONG, NULL, {.slong=8}}, + {"httpReqHandlerTimeout", CTL_LONG, NULL, {.slong=40}}, {"providerSampleInterval", CTL_LONG, NULL, {.slong=30}}, {"providerTimeoutInterval", CTL_LONG, NULL, {.slong=60}}, diff --git a/httpAdapter.c b/httpAdapter.c index df6e596..2719e6c 100644 --- a/httpAdapter.c +++ b/httpAdapter.c @@ -94,11 +94,12 @@ int sfcbSSLMode = 0; /* used as a global sslMode */ int httpLocalOnly = 0; /* 1 = only listen on loopback * interface */ static long hMax; -static int httpProcIdX; +extern int httpProcIdX; static int stopAccepting = 0; static int running = 0; static long keepaliveTimeout = 15; static long keepaliveMaxRequest = 10; +extern long httpReqHandlerTimeout; static long numRequest; static long selectTimeout = 5; /* default 5 sec. timeout for select() before read() */ struct timeval httpSelectTimeout = { 0, 0 }; @@ -2254,6 +2255,9 @@ httpDaemon(int argc, char *argv[], int sslMode, int adapterNum, char *ipAddr, if (getControlNum("keepaliveMaxRequest", &keepaliveMaxRequest)) keepaliveMaxRequest = 10; + if (getControlNum("httpReqHandlerTimeout", &httpReqHandlerTimeout)) + httpReqHandlerTimeout = 40; + char* chunkStr; if (getControlChars("useChunking", &chunkStr) == 0) { if (strcmp(chunkStr, "false") == 0) { @@ -2310,6 +2314,14 @@ httpDaemon(int argc, char *argv[], int sslMode, int adapterNum, char *ipAddr, keepaliveMaxRequest); } + if (httpReqHandlerTimeout == 0) { + mlogf(M_INFO, M_SHOW, "--- Request handler timeout disabled\n"); + httpReqHandlerTimeout = LONG_MAX; + } else { + mlogf(M_INFO, M_SHOW, "--- Request handler timeout: %ld seconds\n", + httpReqHandlerTimeout); + } + /* Label the process by modifying the cmdline */ extern void append2Argv(char *appendstr); extern unsigned int labelProcs; diff --git a/msgqueue.c b/msgqueue.c index 051398b..69d30b3 100644 --- a/msgqueue.c +++ b/msgqueue.c @@ -216,6 +216,20 @@ spGetMsg(int *s, int *from, void *data, unsigned length, MqgStat * mqg) struct iovec iov; struct msghdr msg; + extern int httpProcIdX; + int isReady; + fd_set fds; + struct timeval initialTV = { 0, 0 }, + currentTV; + + if (httpProcIdX) { /* we are a req handler */ + FD_ZERO(&fds); + FD_SET(*s, &fds); + extern long httpReqHandlerTimeout; + initialTV.tv_sec = httpReqHandlerTimeout; + currentTV = initialTV; + } + _SFCB_ENTER(TRACE_MSGQUEUE, "spGetMsg"); _SFCB_TRACE(1, ("--- Receiving from %d length %d", *s, length)); @@ -235,6 +249,21 @@ spGetMsg(int *s, int *from, void *data, unsigned length, MqgStat * mqg) iov.iov_base = data + r; iov.iov_len = length - r; + /* SFCB-0097: Add a select timeout for req handlers */ + if (httpProcIdX) { + isReady = select(*s+1, &fds, NULL, NULL, ¤tTV); + + if (isReady == 0) /* timeout */ + return -2; + + if (isReady < 0) { + if (errno == EINTR) + continue; + else + return spHandleError(s, em); + } + } + if ((n = recvmsg(*s, &msg, 0)) < 0) { if (errno == EINTR) { _SFCB_TRACE(1, (" Receive interrupted %d", currentProc)); @@ -294,7 +323,7 @@ spRcvMsg(int *s, int *from, void **data, unsigned long *length, SpMessageHdr spMsg; static char *em = "rcvMsg receiving from"; MqgStat imqg; - int fromfd; + int fromfd, rc; unsigned long maxlen; int partRecvd = 0, totalRecvd = 0; @@ -305,8 +334,10 @@ spRcvMsg(int *s, int *from, void **data, unsigned long *length, if (mqg == NULL) mqg = &imqg; do { - if ((spGetMsg(s, &fromfd, &spMsg, sizeof(spMsg), mqg)) == -1) + if ((rc = spGetMsg(s, &fromfd, &spMsg, sizeof(spMsg), mqg)) == -1) return spHandleError(s, em); + if (rc < 0) + _SFCB_RETURN(rc); if (mqg && mqg->teintr) { mqg->eintr = 1; @@ -476,7 +507,14 @@ spSendMsg(int *to, int *from, int n, struct iovec *iov, int size) iov[0].iov_base = &spMsg; iov[0].iov_len = sizeof(spMsg); - if ((rc = sendmsg(*to, &msg, 0)) < 0) { + /* SFCB-0097: Suppress SIGPIPE for provider processes, since it probably just + * means the req handler went away, and we handle that error here */ + int flags = 0; + extern int httpProcIdX; + if (httpProcIdX == 0) /* not a req handler */ + flags = MSG_NOSIGNAL; + + if ((rc = sendmsg(*to, &msg, flags)) < 0) { return spHandleError(to, em); } diff --git a/providerMgr.c b/providerMgr.c index 6aa1486..7929724 100644 --- a/providerMgr.c +++ b/providerMgr.c @@ -1277,6 +1277,11 @@ getProviderContext(BinRequestContext * ctx) else if (ctx->rc == MSG_X_EXTENDED_CTL_MSG) { ctx->rc = ctx->ctlXdata->code; } + else if (ctx->rc == -2) { + extern int httpProcIdX; + if (httpProcIdX) + exit(1); + } if (!localMode) { closeSocket(&sockets, COM_ALL, "getProviderContext"); @@ -1301,6 +1306,7 @@ intInvokeProvider(BinRequestContext * ctx, ComSockets sockets) BinResponseHdr *resp = NULL; int fromS; void *heapCtl = markHeap(); + extern int httpProcIdX; #ifdef SFCB_DEBUG struct rusage us, ue; @@ -1412,7 +1418,7 @@ intInvokeProvider(BinRequestContext * ctx, ComSockets sockets) free(resp); resp = NULL; - if (spRecvResult(&sockets.receive, &fromS, (void**) &resp, &size) < 0) { + if ((rc = spRecvResult(&sockets.receive, &fromS, (void**) &resp, &size)) < 0) { size = 0; /* force failure handling */ } @@ -1422,6 +1428,13 @@ intInvokeProvider(BinRequestContext * ctx, ComSockets sockets) if (resp == NULL || size == 0) { resp = calloc(sizeof(BinResponseHdr), 1); resp->rc = CMPI_RC_ERR_FAILED + 1; + if (rc == -2) { + mlogf(M_ERROR, M_SHOW, + "--- req hander %d timed out waiting for provider response\n", + httpProcIdX); + resp->object[0] = setCharsMsgSegment( + "Req handler timed out waiting for provider response"); + } } for (i = 0; i < resp->count; i++) { resp->object[i].data = @@ -1444,7 +1457,7 @@ intInvokeProvider(BinRequestContext * ctx, ComSockets sockets) else if ((ctx->noResp & 1) == 0) { - if (spRecvResult(&sockets.receive, &fromS, (void **) &resp, &size) < 0) { + if ((rc = spRecvResult(&sockets.receive, &fromS, (void**) &resp, &size)) < 0) { size = 0; /* force failure case */ } @@ -1454,6 +1467,13 @@ intInvokeProvider(BinRequestContext * ctx, ComSockets sockets) if (resp == NULL || size == 0) { resp = calloc(sizeof(BinResponseHdr), 1); resp->rc = CMPI_RC_ERR_FAILED + 1; + if (rc == -2) { + mlogf(M_ERROR, M_SHOW, + "--- req hander %d timed out waiting for provider response\n", + httpProcIdX); + resp->object[0] = setCharsMsgSegment( + "Req handler timed out waiting for provider response"); + } } ctx->rCount = ctx->pCount; diff --git a/sfcb.cfg.pre.in b/sfcb.cfg.pre.in index 6affe33..77a2155 100644 --- a/sfcb.cfg.pre.in +++ b/sfcb.cfg.pre.in @@ -122,6 +122,18 @@ basicAuthEntry: _sfcBasicAuthenticate ## Default is 10 #keepaliveMaxRequest: 10 +## Maximum time in seconds a HTTP process (i.e request handler) will wait for +## a provider response before giving up. A timeout implies the provider is hung +## or has crashed. The timeout prevents the handler from waiting indefinitely. +## A value too short may allow insufficient time for long-running processes to +## complete; a value too long may allow handlers to be tied up longer than +## necessary. A value of 0 implies no timeout (wait indefinitely). Note this +## property has no effect on the time a handler will wait on a HTTP client; +## that is governed by selectTimeout or keepaliveTimeout, depending on whether +## or not the handler is in a request. +## Default is 40 +#httpReqHandlerTimeout: 40 + ## The location of the HTTP named socket. This should be someplace writable ## by the user that sfcb runs under. ## Default is /tmp/sfcbHttpSocket hooks/post-receive -- sfcb - Small Footprint CIM Broker |