<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>MQX Software SolutionsのトピックRe: Bug:  Data &amp;quot;corruption&amp;quot; when using detached tasks for CGI or SSI</title>
    <link>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436967#M14614</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;This bug is still present in the RTCS of MQX for KSDK 1.3.&amp;nbsp; The original solution we came up with is not nearly as simple as our current solution.&amp;nbsp; Our current solution involves splitting out the cleanup code in httpsrv_process_cgi() into another function called httpsrv_cleanup_cgi(), (these are in httpsrv_script.c; of course a function prototype for httpsrv_cleanup_cgi() needs to be added to httpsrv_script.h).&amp;nbsp; Here is what it looks like after splitting it:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14514944746461107 jive_text_macro" data-renderedposition="92_8_1232_1056" jivemacro_uid="_14514944746461107"&gt;&lt;P&gt;/*
** Function for CGI request processing
**
** IN:
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SESSION_STRUCT* session - session structure pointer.
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_STRUCT*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server - pointer to server structure (needed for session parameters).
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cgi_name - name of cgi function.
**
** OUT:
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none
**
** Return Value: 
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none
*/
void httpsrv_process_cgi(HTTPSRV_STRUCT *server, HTTPSRV_SESSION_STRUCT *session, char* cgi_name)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SCRIPT_MSG message;

&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(session != NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(server != NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(cgi_name != NULL);

&amp;nbsp;&amp;nbsp;&amp;nbsp; message.session = session;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.type = HTTPSRV_CGI_CALLBACK;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.name = cgi_name;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.ses_tid = _task_get_id();
&amp;nbsp;&amp;nbsp;&amp;nbsp; _lwmsgq_send(server-&amp;gt;script_msgq, (_mqx_max_type*) &amp;amp;message, LWMSGQ_SEND_BLOCK_ON_FULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; /* wait until CGI is processed */
&amp;nbsp;&amp;nbsp;&amp;nbsp; _task_block();

&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
}

void httpsrv_cleanup_cgi(HTTPSRV_SESSION_STRUCT *session)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; /*
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** There is some unread content from client after CGI finished. 
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** It must be read and discarded if we have keep-alive enabled
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** so it does not affect next request.
&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.content_length)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *tmp = NULL;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = _mem_alloc(HTTPSRV_TMP_BUFFER_SIZE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tmp != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t length = session-&amp;gt;request.content_length;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while(length)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32_t retval;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; retval = httpsrv_read(session, tmp, HTTPSRV_TMP_BUFFER_SIZE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((retval == 0) || (retval == RTCS_ERROR))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; length -= retval;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(tmp);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.content_length = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } 
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And then what httpsrv_scipt.h looks like with the prototype added:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14514947289983273" data-renderedposition="1253_8_1232_816" jivemacro_uid="_14514947289983273"&gt;&lt;P&gt;/**HEADER********************************************************************
* 
* Copyright (c) 2013 Freescale Semiconductor;
* All Rights Reserved&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.&amp;nbsp; 
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: httpsrv_prv.h$
*
* Comments:
*
*&amp;nbsp;&amp;nbsp; Header for HTTPSRV.
*
*END************************************************************************/

#ifndef HTTPSRV_SCRIPT_H_
#define HTTPSRV_SCRIPT_H_


#include "httpsrv_prv.h"

#ifdef __cplusplus
extern "C" {
#endif

uint32_t httpsrv_wait_for_cgi(HTTPSRV_SESSION_STRUCT *session);
void httpsrv_detach_script(HTTPSRV_DET_TASK_PARAM* task_params);
HTTPSRV_FN_CALLBACK httpsrv_find_callback(HTTPSRV_FN_LINK_STRUCT* table, char* name, uint32_t* stack_size);
void httpsrv_call_cgi(HTTPSRV_CGI_CALLBACK_FN function, HTTPSRV_SCRIPT_MSG* msg_ptr);
void httpsrv_call_ssi(HTTPSRV_SSI_CALLBACK_FN function, HTTPSRV_SCRIPT_MSG* msg_ptr);
void httpsrv_process_cgi(HTTPSRV_STRUCT *server, HTTPSRV_SESSION_STRUCT *session, char* cgi_name);
void httpsrv_cleanup_cgi(HTTPSRV_SESSION_STRUCT *session);
#ifdef __cplusplus
}
#endif

#endif&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And then finally we need to call httpsrv_cleanup_cgi() at the appropriate times, which is in two places in httpsrv_http_process() in httpsrv_task.c.&amp;nbsp; Basically right after httpsrv_wait_for_cgi() is called.&amp;nbsp; Here is the relevant (modified) code in that function (lines 09 &amp;amp; 40 contain the httpsrv_cleanup_cgi() calls):&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14514951193373436 jive_macro_code jive_text_macro" data-renderedposition="2195_8_1232_688" jivemacro_uid="_14514951193373436"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case HTTPSRV_SES_END_REQ:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(session-&amp;gt;flags &amp;amp; HTTPSRV_FLAG_IS_KEEP_ALIVE))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_set_state(session, HTTPSRV_SES_CLOSE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_wait_for_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_cleanup_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Re-init session */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_set_state(session, HTTPSRV_SES_WAIT_REQ);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.file)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fclose(session-&amp;gt;response.file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_zero(&amp;amp;session-&amp;gt;response, sizeof(session-&amp;gt;response));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.auth.user_id != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;request.auth.user_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.user_id = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.password = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;time = RTCS_time_get();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;timeout = HTTPSRVCFG_KEEPALIVE_TO;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;flags = HTTPSRV_FLAG_IS_KEEP_ALIVE | HTTPSRV_FLAG_PROCESS_HEADER;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case HTTPSRV_SES_CLOSE:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * If session did not time out; wait for lock. If waiting
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * for lock timed-out, check session timeout again.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (time_interval &amp;lt; session-&amp;gt;timeout)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (httpsrv_wait_for_cgi(session) == MQX_LWSEM_WAIT_TIMEOUT)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_cleanup_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_close(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;valid = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In addition, there is a timeout for CGI tasks.&amp;nbsp; We found that if we were transferring a large file (for instance a firmware update), the CGI task would time out and get killed.&amp;nbsp; So we added a an additional_timeout field to the CGI callback table (this additional_timeout gets set to 0 for tasks that run fine with the default timeout).&amp;nbsp; When the CGI callback is found in httpsrv_find_callback(), the additional_timeout is one of the parameters that is filled in and returned (similar to stack_size), or it is zeroed in the case that no callback is returned.&amp;nbsp; Then in httpsrv_script_task() in httpsrv_task.c, after httpsrv_find_callback() is called, the additional_timeout found is added to message.session-&amp;gt;timeout.&amp;nbsp; I leave this up to the reader to decide how to implement, as I am not particularly confident this is the best way to solve the issue.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last note, there does seem to be bug in SOCK_STREAM_recv(), which is in sock_stream.c.&amp;nbsp; I am covering this in another post called:&amp;nbsp; SOCK_STREAM_recv() bug drops data on receive timeout.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Wed, 30 Dec 2015 17:20:50 GMT</pubDate>
    <dc:creator>bowe</dc:creator>
    <dc:date>2015-12-30T17:20:50Z</dc:date>
    <item>
      <title>Bug:  Data "corruption" when using detached tasks for CGI or SSI</title>
      <link>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436964#M14611</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;We are using MQX for Kinetis SDK 1.1.&amp;nbsp; We think we have found a bug in the CGI handling.&amp;nbsp; I have searched the forums a little, and haven’t really seen anything similar.&amp;nbsp; In looking at the code for MQX for Kinetis SDK 1.2, it looks like this bug has not been fixed.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;We finally saw this bug when we went to upload a relatively large file (28 KB) to a CGI endpoint, where the handling function was run in its own task (which I will refer to as the handling task, which is distinct form the CGI handler task).&amp;nbsp; Essentially what was happening was the is the CGI handler was not waiting for the handling task to finish, and would strip the HTTP data out (assuming it was left over data that the handling task didn’t process) before the handling task could receive it.&amp;nbsp; If the handling function was run in the CGI handler task, then it was a function call for the CGI handler instead of a task create, so it would wait for the handling function to finish.&amp;nbsp; On a small file, the handling task could grab the data quickly before the CGI handler trashed it.&amp;nbsp; So we only saw this issue on (relatively) larger files/data and when the handling function was run in its own task.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;We have found a solution that seems to work.&amp;nbsp; We created a function modeled after &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black; background: silver;"&gt;RTCS_task_create&lt;/SPAN&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black;"&gt;()&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt; that would create the task and wait for it to complete (unsurprisingly called &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black; background: silver;"&gt;RTCS_task_create_and_wait&lt;/SPAN&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black;"&gt;()&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;).&amp;nbsp; Instead of using a semaphore and waiting for the child (which is the handling task) to unblock the parent (the CGI handler task), we had the parent watch for the child to terminate.&amp;nbsp; We could not find an MQX function to wait for a task to complete or terminate, so we mimicked that behavior by waiting for the child task descriptor to no longer exist or to list a different parent (in the case that a new task is spawned from a different parent task with the same task ID shortly after our child task terminates).&amp;nbsp; We chose this method over the semaphore method because we felt it was more robust to the child task crashing, which we were concerned would probably cause the CGI handler task to deadlock in the semaphore based approach.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;The following function prototype was added to rtcs25x.h:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_1431720484796304" data-renderedposition="380_8_1232_128" jivemacro_uid="_1431720484796304" modifiedtitle="true"&gt;&lt;P&gt;extern uint32_t RTCS_task_create_and_wait&lt;/P&gt;&lt;P&gt;(&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; char&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *name,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; priority,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stacksize,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; void (_CODE_PTR_&amp;nbsp; start)(void *, void *),&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; void&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *arg&lt;/P&gt;&lt;P&gt;);&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;And the following definition was added to rtcstask.c:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14317204183523152 jive_macro_code jive_text_macro" data-renderedposition="594_8_1232_960" jivemacro_uid="_14317204183523152" modifiedtitle="true"&gt;&lt;P&gt;/*FUNCTION*-------------------------------------------------------------&lt;/P&gt;&lt;P&gt;*&lt;/P&gt;&lt;P&gt;* Function Name&amp;nbsp;&amp;nbsp; : RTCS_task_create_and_wait&lt;/P&gt;&lt;P&gt;* Returned Values : uint32_t (error code)&lt;/P&gt;&lt;P&gt;* Comments&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/P&gt;&lt;P&gt;*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Create a task and wait for it to finish running.&lt;/P&gt;&lt;P&gt;*&lt;/P&gt;&lt;P&gt;*END*-----------------------------------------------------------------*/&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;uint32_t RTCS_task_create_and_wait&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; (&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *name,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; priority,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stacksize,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void (_CODE_PTR_&amp;nbsp; start)(void *, void *),&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *arg&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; )&lt;/P&gt;&lt;P&gt;{ /* Body */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; TASK_TEMPLATE_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp; task_template;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; struct rtcs_task_state&amp;nbsp; task;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;#if (RTCSCFG_ENABLE_ASSERT_PRINT==1) ||&amp;nbsp; (RTCSCFG_ENABLE_ASSERT==1)&lt;/P&gt;&lt;P&gt;&amp;nbsp; /* for TCP/IP task we bypass this check as for this one */&lt;/P&gt;&lt;P&gt;&amp;nbsp; /* priority = _RTCSTASK_priority */&lt;/P&gt;&lt;P&gt;&amp;nbsp; if(TRUE == _RTCS_initialized)&lt;/P&gt;&lt;P&gt;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(priority&amp;gt;_RTCSTASK_priority);&lt;/P&gt;&lt;P&gt;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;#endif&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; RTCS_sem_init(&amp;amp;task.sem);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task.start = start;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task.arg&amp;nbsp;&amp;nbsp; = arg;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task.error = RTCS_OK;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _mem_zero((unsigned char *)&amp;amp;task_template, sizeof(task_template));&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task_template.TASK_NAME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = name;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task_template.TASK_PRIORITY&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = priority;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task_template.TASK_STACKSIZE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = stacksize;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task_template.TASK_ADDRESS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = RTCS_task;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; task_template.CREATION_PARAMETER = (uint32_t)&amp;amp;task;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _task_id myTID = _task_get_id();&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; _task_id childTID = _task_create(0, 0, (uint32_t)&amp;amp;task_template);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; if (childTID == MQX_NULL_TASK_ID) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_sem_destroy(&amp;amp;task.sem);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return RTCSERR_CREATE_FAILED;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; } /* Endif */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; // Wait until its out on its own&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; RTCS_sem_wait(&amp;amp;task.sem);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; RTCS_sem_destroy(&amp;amp;task.sem);&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Watch it die&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TD_STRUCT_PTR childTD = (TD_STRUCT_PTR) _task_get_td(childTID);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while(childTD != NULL)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Paternity Test:&amp;nbsp; If this task is no longer my child, abandon it&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(myTID != childTD-&amp;gt;PARENT)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sched_yield();&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; childTD = (TD_STRUCT_PTR) _task_get_td(childTID);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp; return task.error;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;} /* Endbody */&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;Then &lt;STRONG&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black; background: silver;"&gt;RTCS_task_create&lt;/SPAN&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black;"&gt;()&lt;/SPAN&gt;&lt;/STRONG&gt; was changed to &lt;STRONG&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black; background: silver;"&gt;RTCS_task_create_and_wait&lt;/SPAN&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black;"&gt;()&lt;/SPAN&gt;&lt;/STRONG&gt; in the function &lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;&lt;STRONG&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black; background: silver;"&gt;httpsrv_detach_script&lt;/SPAN&gt;&lt;SPAN style="font-size: 10.0pt; font-family: Consolas; color: black;"&gt;()&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;/SPAN&gt; in httpsrv_script.c:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14317205468419700 jive_macro_code jive_text_macro" data-renderedposition="1640_8_1232_448" jivemacro_uid="_14317205468419700" modifiedtitle="true"&gt;&lt;P&gt;/*&lt;/P&gt;&lt;P&gt;** Detach script processing to separate task&lt;/P&gt;&lt;P&gt;**&lt;/P&gt;&lt;P&gt;** IN:&lt;/P&gt;&lt;P&gt;**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SESSION_STRUCT* session - session structure pointer.&lt;/P&gt;&lt;P&gt;**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_STRUCT *server - pointer to server structure (needed for session parameters).&lt;/P&gt;&lt;P&gt;**&lt;/P&gt;&lt;P&gt;** OUT:&lt;/P&gt;&lt;P&gt;**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none&lt;/P&gt;&lt;P&gt;**&lt;/P&gt;&lt;P&gt;** Return Value: &lt;/P&gt;&lt;P&gt;**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;void httpsrv_detach_script(HTTPSRV_DET_TASK_PARAM* task_params)&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mqx_uint&amp;nbsp; error;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mqx_uint&amp;nbsp; priority;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; error = _task_get_priority(MQX_NULL_TASK_ID, &amp;amp;priority);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (error != MQX_OK)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; error = RTCS_task_create_and_wait(HTTPSRV_DETACHED_SCRIPT_TASK_NAME, priority, task_params-&amp;gt;stack_size, httpsrv_detached_task, (void *)task_params);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (error != MQX_OK)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;Like I said, this seems to work for us, but is probably not the best or most eloquent solution.&amp;nbsp; I am certainly open for suggestions on improvements.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 11.0pt; font-family: 'Calibri','sans-serif'; color: #1f497d;"&gt;-Bowe&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 15 May 2015 20:16:47 GMT</pubDate>
      <guid>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436964#M14611</guid>
      <dc:creator>bowe</dc:creator>
      <dc:date>2015-05-15T20:16:47Z</dc:date>
    </item>
    <item>
      <title>Re: Bug:  Data "corruption" when using detached tasks for CGI or SSI</title>
      <link>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436965#M14612</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P style="margin-bottom: .0001pt;"&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;Hi Bowe,&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;First of all, I will ask you for your code to test this issue (including your solution too) and validate with development team, so they could solve it on next releases.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;You comment about you do not prefer semaphore based solution due if child task crashes it will make CGI handler task to crash too, but, what happens if in your solution, your child task crashes? It will not terminate and the while loop will be running always so it will cause CGI handler task to crash too?&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;Another solution (maybe it could be better) could be to implement a semaphore (or mutex if you desire so) technique, and to avoid child task to get crashed, you can implement a watchdog timer task inside your child task, this way you ensure your child task will not get crashed or loop.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;You can find more information about watchdog timer (in mqx) on MQX's reference manual located at: C:\Freescale\KSDK_1.2.0\doc\rtos\mqx, also, attached document explains more about it.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;I hope this feedback can help you.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;Regards,&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 10.5pt; font-family: Helvetica, sans-serif;"&gt;Isaac Avila&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Mon, 08 Jun 2015 17:49:39 GMT</pubDate>
      <guid>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436965#M14612</guid>
      <dc:creator>isaacavila</dc:creator>
      <dc:date>2015-06-08T17:49:39Z</dc:date>
    </item>
    <item>
      <title>Re: Bug:  Data "corruption" when using detached tasks for CGI or SSI</title>
      <link>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436966#M14613</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I cannot really include my code, but I can try to write a snippet that exposes the issue.&amp;nbsp; I suspect that just adding a 1 ms delay with _time_delay(1) in a detached CGI task will show the bug.&amp;nbsp; I will reply back if/when I get code that exposes this.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Yes, given your explanation, it would seem that the solution I posted is not as robust against the child process crashing as I though.&amp;nbsp; In my head, I was thinking that if the child task crashed, MQX would remove it from the task queue; however, I do not believe this is the case.&amp;nbsp; In this case, the CGI handler would not crash, but it would never terminate.&amp;nbsp; I suppose an additional check on the child task to make sure it is still running/viable is required.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The watchdog timer inside the child task is certainly an option.&amp;nbsp; I do not like the idea of complicating the child task, and the break in abstraction it causes.&amp;nbsp; I would much rather somehow provide this feature as a wrapper around the child.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;-Bowe&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 07 Jul 2015 23:44:48 GMT</pubDate>
      <guid>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436966#M14613</guid>
      <dc:creator>bowe</dc:creator>
      <dc:date>2015-07-07T23:44:48Z</dc:date>
    </item>
    <item>
      <title>Re: Bug:  Data "corruption" when using detached tasks for CGI or SSI</title>
      <link>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436967#M14614</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;This bug is still present in the RTCS of MQX for KSDK 1.3.&amp;nbsp; The original solution we came up with is not nearly as simple as our current solution.&amp;nbsp; Our current solution involves splitting out the cleanup code in httpsrv_process_cgi() into another function called httpsrv_cleanup_cgi(), (these are in httpsrv_script.c; of course a function prototype for httpsrv_cleanup_cgi() needs to be added to httpsrv_script.h).&amp;nbsp; Here is what it looks like after splitting it:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14514944746461107 jive_text_macro" data-renderedposition="92_8_1232_1056" jivemacro_uid="_14514944746461107"&gt;&lt;P&gt;/*
** Function for CGI request processing
**
** IN:
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SESSION_STRUCT* session - session structure pointer.
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_STRUCT*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server - pointer to server structure (needed for session parameters).
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cgi_name - name of cgi function.
**
** OUT:
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none
**
** Return Value: 
**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; none
*/
void httpsrv_process_cgi(HTTPSRV_STRUCT *server, HTTPSRV_SESSION_STRUCT *session, char* cgi_name)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SCRIPT_MSG message;

&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(session != NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(server != NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; RTCS_ASSERT(cgi_name != NULL);

&amp;nbsp;&amp;nbsp;&amp;nbsp; message.session = session;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.type = HTTPSRV_CGI_CALLBACK;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.name = cgi_name;
&amp;nbsp;&amp;nbsp;&amp;nbsp; message.ses_tid = _task_get_id();
&amp;nbsp;&amp;nbsp;&amp;nbsp; _lwmsgq_send(server-&amp;gt;script_msgq, (_mqx_max_type*) &amp;amp;message, LWMSGQ_SEND_BLOCK_ON_FULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp; /* wait until CGI is processed */
&amp;nbsp;&amp;nbsp;&amp;nbsp; _task_block();

&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
}

void httpsrv_cleanup_cgi(HTTPSRV_SESSION_STRUCT *session)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; /*
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** There is some unread content from client after CGI finished. 
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** It must be read and discarded if we have keep-alive enabled
&amp;nbsp;&amp;nbsp;&amp;nbsp; ** so it does not affect next request.
&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.content_length)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *tmp = NULL;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = _mem_alloc(HTTPSRV_TMP_BUFFER_SIZE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tmp != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t length = session-&amp;gt;request.content_length;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while(length)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32_t retval;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; retval = httpsrv_read(session, tmp, HTTPSRV_TMP_BUFFER_SIZE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((retval == 0) || (retval == RTCS_ERROR))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; length -= retval;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(tmp);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.content_length = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } 
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And then what httpsrv_scipt.h looks like with the prototype added:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14514947289983273" data-renderedposition="1253_8_1232_816" jivemacro_uid="_14514947289983273"&gt;&lt;P&gt;/**HEADER********************************************************************
* 
* Copyright (c) 2013 Freescale Semiconductor;
* All Rights Reserved&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.&amp;nbsp; 
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: httpsrv_prv.h$
*
* Comments:
*
*&amp;nbsp;&amp;nbsp; Header for HTTPSRV.
*
*END************************************************************************/

#ifndef HTTPSRV_SCRIPT_H_
#define HTTPSRV_SCRIPT_H_


#include "httpsrv_prv.h"

#ifdef __cplusplus
extern "C" {
#endif

uint32_t httpsrv_wait_for_cgi(HTTPSRV_SESSION_STRUCT *session);
void httpsrv_detach_script(HTTPSRV_DET_TASK_PARAM* task_params);
HTTPSRV_FN_CALLBACK httpsrv_find_callback(HTTPSRV_FN_LINK_STRUCT* table, char* name, uint32_t* stack_size);
void httpsrv_call_cgi(HTTPSRV_CGI_CALLBACK_FN function, HTTPSRV_SCRIPT_MSG* msg_ptr);
void httpsrv_call_ssi(HTTPSRV_SSI_CALLBACK_FN function, HTTPSRV_SCRIPT_MSG* msg_ptr);
void httpsrv_process_cgi(HTTPSRV_STRUCT *server, HTTPSRV_SESSION_STRUCT *session, char* cgi_name);
void httpsrv_cleanup_cgi(HTTPSRV_SESSION_STRUCT *session);
#ifdef __cplusplus
}
#endif

#endif&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And then finally we need to call httpsrv_cleanup_cgi() at the appropriate times, which is in two places in httpsrv_http_process() in httpsrv_task.c.&amp;nbsp; Basically right after httpsrv_wait_for_cgi() is called.&amp;nbsp; Here is the relevant (modified) code in that function (lines 09 &amp;amp; 40 contain the httpsrv_cleanup_cgi() calls):&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14514951193373436 jive_macro_code jive_text_macro" data-renderedposition="2195_8_1232_688" jivemacro_uid="_14514951193373436"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case HTTPSRV_SES_END_REQ:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(session-&amp;gt;flags &amp;amp; HTTPSRV_FLAG_IS_KEEP_ALIVE))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_set_state(session, HTTPSRV_SES_CLOSE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_wait_for_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_cleanup_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Re-init session */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_set_state(session, HTTPSRV_SES_WAIT_REQ);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.file)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fclose(session-&amp;gt;response.file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_zero(&amp;amp;session-&amp;gt;response, sizeof(session-&amp;gt;response));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.auth.user_id != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;request.auth.user_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.user_id = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.password = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;time = RTCS_time_get();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;timeout = HTTPSRVCFG_KEEPALIVE_TO;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;flags = HTTPSRV_FLAG_IS_KEEP_ALIVE | HTTPSRV_FLAG_PROCESS_HEADER;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case HTTPSRV_SES_CLOSE:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * If session did not time out; wait for lock. If waiting
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * for lock timed-out, check session timeout again.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (time_interval &amp;lt; session-&amp;gt;timeout)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (httpsrv_wait_for_cgi(session) == MQX_LWSEM_WAIT_TIMEOUT)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_cleanup_cgi(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_ses_close(session);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;valid = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In addition, there is a timeout for CGI tasks.&amp;nbsp; We found that if we were transferring a large file (for instance a firmware update), the CGI task would time out and get killed.&amp;nbsp; So we added a an additional_timeout field to the CGI callback table (this additional_timeout gets set to 0 for tasks that run fine with the default timeout).&amp;nbsp; When the CGI callback is found in httpsrv_find_callback(), the additional_timeout is one of the parameters that is filled in and returned (similar to stack_size), or it is zeroed in the case that no callback is returned.&amp;nbsp; Then in httpsrv_script_task() in httpsrv_task.c, after httpsrv_find_callback() is called, the additional_timeout found is added to message.session-&amp;gt;timeout.&amp;nbsp; I leave this up to the reader to decide how to implement, as I am not particularly confident this is the best way to solve the issue.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last note, there does seem to be bug in SOCK_STREAM_recv(), which is in sock_stream.c.&amp;nbsp; I am covering this in another post called:&amp;nbsp; SOCK_STREAM_recv() bug drops data on receive timeout.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 30 Dec 2015 17:20:50 GMT</pubDate>
      <guid>https://community.nxp.com/t5/MQX-Software-Solutions/Bug-Data-quot-corruption-quot-when-using-detached-tasks-for-CGI/m-p/436967#M14614</guid>
      <dc:creator>bowe</dc:creator>
      <dc:date>2015-12-30T17:20:50Z</dc:date>
    </item>
  </channel>
</rss>

