From:
address@hidden
[mailto:address@hidden On Behalf
Of Baptiste Chaboud-crousaz
Sent: Thursday, August 06, 2009 5:51 AM
To: address@hidden
Subject: Re: [lwip-users] Problem with NULL pcb->callback_arg
Hi all,
Since my problem is not resolved, I ask you again to help me.
I use the HTTP (RAW version) server provided by the lwip site in the
/contrib/apps/httpserver_raw folder.
Sometimes, the argument passed to http_sent is NULL which leads an hardfault
exception. In the majority of cases, there is no problem. This problem is
avoided or limited when I increases the size of MEM_SIZE. But I have to
drastically reduce this size to meet my hardware requirements.
My understanding is that a memory allocation is done out the memory space
dedicted to lwip.
But I don' understand how it can be possible. All the results of memory
allocation are checked. Would it be possible that there is a bug in lwip? If
yes where?
What should I do?????
Best regards.
Baptiste
Quoting Baptiste
Chaboud-crousaz <address@hidden>:
>
>
> Hi,
>
> For a better understanding I give a part of the code of my
HTTP server:
>
> ===============================================
>
> void httpd_init(void)
> {
> struct tcp_pcb *pcb;
>
> pcb = tcp_new();
> tcp_bind(pcb, IP_ADDR_ANY, 80);
> pcb = tcp_listen(pcb);
> tcp_accept(pcb, http_accept);
> }
>
> ===============================================
>
> static err_t
> http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
> {
> struct http_connect_state* hcs;
>
> tcp_setprio(pcb, TCP_PRIO_MIN);
>
> /* Allocate memory for the structure that holds the
state of the
> connection. */
> hcs = mem_malloc(sizeof(struct http_connect_state));
>
> if (hcs == NULL) {
> return ERR_MEM;
> }
>
> /* Initialize the structure. */
> hcs->file
= NULL;
> hcs->resource_id = 0;
> hcs->method_id
= 0;
> hcs->retries =
0;
>
> /* Tell TCP that this is the structure we wish to be
passed for
> our callbacks. */
> tcp_arg(pcb, hcs);
>
> /* Tell TCP that we wish to be informed of incoming
data by a
> call to the http_recv() function. */
> tcp_recv(pcb, http_recv);
>
> tcp_err(pcb, conn_err);
>
> tcp_poll(pcb, http_poll, 4);
>
> return ERR_OK;
> }
>
> ===============================================
>
> static err_t
> http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
> {
> struct http_connect_state* hcs;
>
> hcs = arg;
>
> if (ERR_OK == err)
> {
> if (NULL != p)
> {
> /* Inform TCP
that we have taken the data. */
> tcp_recved(pcb,
p->tot_len);
>
> if (hcs->file
== NULL)
> {
>
ProcessHttpRequest(hcs, p, &(pcb->remote_ip));
>
>
if (hcs->file != NULL)
>
{
>
pbuf_free(p);
>
send_data(pcb, hcs);
>
>
/* Tell TCP that we wish be to informed
of data
> that has been
>
successfully sent by a call to the
http_sent()
> function. */
>
tcp_sent(pcb, http_sent);
>
}
>
else
>
{
>
pbuf_free(p);
>
p = NULL;
>
}
> }
> else
> {
>
pbuf_free(p);
>
p = NULL;
> }
> }
>
> if (NULL == p)
> {
> close_conn(pcb,
hcs);
> }
> }
>
> return err;
> }
>
> ===============================================
>
> static err_t
> http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
> {
> struct http_connect_state* hcs;
>
> if(arg != NULL)
> {
> hcs = arg;
> hcs->retries = 0;
> send_data(pcb, hcs);
> }
>
> return ERR_OK;
> }
>
> ===============================================
>
> static void
> close_conn(struct tcp_pcb *pcb, struct http_connect_state* hcs)
> {
> tcp_arg(pcb, NULL);
> tcp_sent(pcb, NULL);
> tcp_recv(pcb, NULL);
>
> if(hcs->file) {
> wfs_close(hcs->file);
> hcs->file = NULL;
> }
>
> mem_free(hcs);
> tcp_close(pcb);
> }
>
> ===============================================
>
> As you can see at the HTTP init, the http_accept is set as
callback
> for ACCEPT and in http_recv, http_sent is set as callback which will
> be called by TCP_EVENT_SENT.
>
> When I use a single web browser there is no problem: the arg
value
> passed to http_sent is never NULL. But when I launch another web
> browser, this parameter becomes sometimes NULL. It seems to be when
> the stack receives the new SYN frame from the client.
>
> You said "That could be a hint that you are writing
beyond allocated memory
> somwhere and overwrite the memory where the PCB lies with zeros". But
> I always check the returned value when I make a memory allocation. If
> the functions used for memory allocation return an invalid space =>
> there is a bug in the stack!
>
> Baptiste
>
> Quoting "address@hidden" <address@hidden>:
>> Baptiste Chaboud-crousaz wrote:
>>>
>>> Sometimes, the face trouble with my callback http_connect -
>>> called by the macro TCP_EVENT_SENT - because
"arg" is null.
>>>
>>
>> I don't understand that one:
>> a) there is no function 'http_connect' in the code you posted
>> b) TCP_EVENT_SENT calls the function set by calling tcp_sent(pcb, fn)
-
>> the code you posted doesn't call tcp_sent().
>> c) I would have thought a connect function would be used with a
client,
>> not a server - whereas an accept function (as you posted) is used with
>> a server, not a client)
>>
>>> My understanding is that the http_accept function binds a pcb
to
>>> an argument by a call to tcp_arg(...). I don't undersatnd
why
>>> sometimes my callback is called with a NULL arg!!!
>>>
>>> This issue seems to be avoided/limited by increasing the size
of
>>> MEM_SIZE and PBUF_POOL_SIZE.
>>>
>>
>> That could be a hint that you are writing beyond allocated memory
>> somwhere and overwrite the memory where the PCB lies with zeros...
>>
>>> If anybody has an idea, let me knwo about it...
>>>
>>
>> Except for the above, I'm afraid I don't have an idea. Unless you call
>> *tcp_arg(pcb, NULL) somewhere else, of course...*
>>
>> Does the argument get NULL during the connection or right at the
start?
>>
>>
>> Simon
>>
>>
>> _______________________________________________
>> lwip-users mailing list
>> address@hidden
>> http://lists.nongnu.org/mailman/listinfo/lwip-users