[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-users] [lwip] lwIP crashing after 17MB of data transfer
From: |
psheer |
Subject: |
[lwip-users] [lwip] lwIP crashing after 17MB of data transfer |
Date: |
Wed, 08 Jan 2003 23:57:42 -0000 |
Hi Adam and others
I still have a problem with lwip-cvs-20020215 that I had
with a previous version, lwip-cvs-20020114
I have created a BSD socket layer (way below) for PaulOS.
I use nc (net cat) to dump many megs through this echo
server...
[[[
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <socket.h>
#include "lwip/lwip/src/include/lwip/stats.h"
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
static int listen_socket (int listen_port)
{
struct sockaddr_in a;
int s;
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
perror ("socket() failed");
return -1;
}
memset (&a, 0, sizeof (a));
a.sin_port = htons (listen_port);
a.sin_family = AF_INET;
if (bind (s, (struct sockaddr *) &a, sizeof (a)) < 0) {
perror ("bind() failed");
close (s);
return -1;
}
printf ("accepting connections on port %d\n", (int) listen_port);
listen (s, 10);
return s;
}
int main (int argc, char **argv)
{
int fd, s, r, l = 0;
char buf[2048];
struct sockaddr_in a;
int i = 0;
s = listen_socket (81);
for (;;) {
l = sizeof (struct sockaddr_in);
fd = accept (s, (struct sockaddr *) &a, &l);
for (;;) {
char *p;
r = read (fd, buf, 1024);
if (r <= 0) {
perror ("read");
break;
}
p = buf;
while (r > 0) {
int c;
c = write (fd, p, min (1024, r));
if (c <= 0) {
perror ("write");
goto out;
}
p += c;
r -= c;
}
}
out:
close (fd);
}
}
]]]
but after dumping 17 megs it dies unexpectedly. I turn
on debug, but with debug on, it works perfectly. It also
works perfectly if I add a small delay to the main loop.
It seems to only break when it runs flat out, and then
always in exactly the same place. After it dies I can
still ping it though.
I added code to the above to check memory usage but
memory usage is really very small.
I am using much more memory than the default lwipopts.h
- i have raised most of the values by an order of
magnitude. Note that this is running on an Atmel ARM7TDMI
with 512kB of SRAM.
any ideas??
-paul
---------------------------
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "errno.h"
#include "file.h"
#include "list.h"
#include "sys/ioctl.h"
static int lwip_error_to_errno (int v)
{
const int e[] =
{ 0, ENOMEM, ENOBUFS, ECONNABORTED, ECONNRESET, ESHUTDOWN, ENOTCONN,
EINVAL, EINVAL,
EHOSTUNREACH,
EADDRINUSE
};
return e[-v];
}
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
LIST_TYPE_DECLARE (incoming_item, struct tcp_pcb * pcb;);
LIST_TYPE_DECLARE (packet_item, struct pbuf *pbuf;);
static void incoming_free (incoming_item * p)
{
if (p->pcb) {
tcp_arg (p->pcb, NULL);
tcp_sent (p->pcb, NULL);
tcp_recv (p->pcb, NULL);
tcp_close (p->pcb);
}
}
static void packet_free (packet_item * p)
{
pbuf_free (p->pbuf);
}
struct socket_info {
#define LISTENER_MAGIC 0x95de8a3b
#define STREAM_MAGIC 0x3fd740ab
int type;
int ref; /* number of times dup'ed */
struct tcp_pcb *pcb;
union {
struct {
int listener_queue_max_len;
LIST_DECLARE (incoming_list, incoming_item); /* queued
incoming connections for
listening sockets */
} listener;
struct {
LIST_DECLARE (packet_list, packet_item); /* queued incoming
packets for connected
sockets */
struct pbuf *current;
int in_packet_offset;
} stream;
} d;
};
static void _socket_close (struct socket_info *info)
{
if (info->pcb) {
tcp_arg (info->pcb, NULL);
tcp_sent (info->pcb, NULL);
tcp_recv (info->pcb, NULL);
tcp_close (info->pcb);
info->pcb = 0;
}
}
static err_t _socket_poll (void *arg, struct tcp_pcb *pcb)
{
if (arg == NULL) {
tcp_close (pcb);
}
#if 0
else {
send_data (pcb, (struct http_state *) arg);
}
#endif
return ERR_OK;
}
static void _socket_error (void *arg, err_t err)
{
struct socket_info *info = (struct socket_info *) arg;
ldeleteall (info->d.stream.packet_list);
if (info->pcb)
_socket_close (info);
}
static void _listener_error (void *arg, err_t err)
{
struct socket_info *info = (struct socket_info *) arg;
ldeleteall (info->d.listener.incoming_list);
if (info->pcb)
_socket_close (info);
}
static void *socket_dup (void *o)
{
struct socket_info *info = (struct socket_info *) o;
info->ref++;
return info;
}
static void socket_close (void *o)
{
struct socket_info *info = (struct socket_info *) o;
if (info->ref) {
info->ref--;
return;
}
if (info->type == LISTENER_MAGIC) {
ldeleteall (info->d.listener.incoming_list);
_socket_close (info);
} else {
ldeleteall (info->d.stream.packet_list);
_socket_close (info);
}
free (o);
}
static inline int _socket_write_space (struct socket_info *info)
{
if (stats.memp[MEMP_TCP_SEG].used > stats.memp[MEMP_TCP_SEG].avail / 2)
return 0;
return tcp_sndbuf (info->pcb);
}
static int socket_write_space (void *o, int n)
{
struct socket_info *info = (struct socket_info *) o;
if (info->type != STREAM_MAGIC)
return -1;
if (!info->pcb)
return -1;
return _socket_write_space (info);
}
static int socket_write (void *o, unsigned char *s, int len)
{
struct socket_info *info = (struct socket_info *) o;
err_t err;
if (info->type != STREAM_MAGIC) {
errno = ENOTSOCK;
return -1;
}
if (!info->pcb) {
errno = ENOTCONN;
return -1;
}
do {
/* explicit (i.e. one extra) */
global_callback ();
if (!info->pcb) /* socket closed */
return 0;
} while (_socket_write_space (info) <= 0);
len = min (len, tcp_sndbuf (info->pcb));
err = tcp_write (info->pcb, s, len, 1);
if (err == ERR_OK) {
if (!info->pcb->unacked)
tcp_output (info->pcb);
return len;
}
errno = lwip_error_to_errno (err);
return -1;
}
static int socket_write_queue (void *o)
{
struct socket_info *info = (struct socket_info *) o;
struct tcp_seg *unsent;
int total = 0;
if (info->type != STREAM_MAGIC)
return -1;
if (!info->pcb)
return -1;
for (unsent = info->pcb->unsent; unsent; unsent = unsent->next)
total += unsent->len;
return total;
}
static int socket_write_nonblock (void *o, unsigned char *s, int len)
{
if (socket_write_space (o, 0))
return socket_write (o, s, len);
errno = EAGAIN;
return -1;
}
err_t _socket_recv (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct socket_info *info = (struct socket_info *) arg;
if (err == ERR_OK && p == NULL) {
_socket_close (info);
}
if (err == ERR_OK && p != NULL) {
struct packet_item *j;
/* record the packet in our list for later reading */
lappend (info->d.stream.packet_list);
j = ltail (info->d.stream.packet_list);
j->pbuf = p;
}
return ERR_OK;
}
static int socket_read (void *o, unsigned char *s, int len)
{
struct socket_info *info = (struct socket_info *) o;
struct packet_item *j;
int r = 0;
if (info->type != STREAM_MAGIC) {
errno = ENOTSOCK;
return -1;
}
if (!info->pcb) {
errno = ENOTCONN;
return -1;
}
for (;;) {
/* explicit (i.e. always one extra callback) */
global_callback ();
if (!info->pcb) /* socket closed */
return 0;
if ((j = lhead (info->d.stream.packet_list)))
if (j->pbuf->tot_len > 0)
break;
}
/* start at the first pbuf in the segment */
if (!info->d.stream.current) {
info->d.stream.current = j->pbuf;
info->d.stream.in_packet_offset = 0;
}
/* FIXME: quadruple check this algorithm */
for (;;) {
int c;
c = min (len, info->d.stream.current->len -
info->d.stream.in_packet_offset);
if (!c)
break; /* out of space */
memcpy (s, info->d.stream.current->payload +
info->d.stream.in_packet_offset, c);
s += c;
r += c;
len -= c;
info->d.stream.in_packet_offset += c;
if (info->d.stream.in_packet_offset == info->d.stream.current->len) {
info->d.stream.current = info->d.stream.current->next;
info->d.stream.in_packet_offset = 0;
}
if (!info->d.stream.current) {
/* consumed all pbufs, so delete segment */
ldeleteinc (info->d.stream.packet_list, j);
if (!j)
break; /* nothing left to process */
info->d.stream.current = j->pbuf;
}
}
tcp_recved (info->pcb, r);
tcp_output (info->pcb);
return r;
}
static int socket_read_avail (void *o, int n)
{
packet_item *j;
int total = 0;
struct socket_info *info = (struct socket_info *) o;
if (info->type == STREAM_MAGIC) {
if (!info->pcb)
return -1;
lsearchforward (info->d.stream.packet_list, j, total +=
j->pbuf->tot_len);
return total;
}
/* return a count of the incoming connections */
return lcount (info->d.listener.incoming_list);
}
static int socket_read_nonblock (void *o, unsigned char *s, int len)
{
if (socket_read_avail (o, 0))
return socket_read (o, s, len);
errno = EAGAIN;
return -1;
}
static err_t _socket_accept (void *arg, struct tcp_pcb *pcb, err_t err)
{
struct socket_info *info = (struct socket_info *) arg;
incoming_item *j;
if (lcount (info->d.listener.incoming_list) >=
info->d.listener.listener_queue_max_len)
return ERR_MEM;
lappend (info->d.listener.incoming_list);
j = ltail (info->d.listener.incoming_list);
j->pcb = pcb;
return ERR_OK;
}
static void *socket_socket (void *param, int arg1, int arg2)
{
struct socket_info *info;
info = (struct socket_info *) malloc (sizeof (struct socket_info));
if (!info) {
errno = ENOMEM;
return 0;
}
memset (info, 0, sizeof (struct socket_info));
info->pcb = tcp_new ();
if (!info->pcb) {
errno = ENOMEM;
free (info);
return 0;
}
info->type = LISTENER_MAGIC;
linit (info->d.listener.incoming_list, incoming_item, incoming_free);
tcp_err (info->pcb, _listener_error);
return (void *) info;
}
static int socket_ioctl (void *o, int cmd, int *config)
{
struct socket_info *info = (struct socket_info *) o;
struct sockaddr_in *s = (struct sockaddr_in *) config;
err_t r;
switch (cmd) {
case SIOBIND:
if (info->type != LISTENER_MAGIC) {
errno = ENOTSOCK;
return -1;
}
r = tcp_bind (info->pcb, (struct ip_addr *) &s->sin_addr, ntohs
(s->sin_port));
if (r != ERR_OK) {
errno = lwip_error_to_errno (r);
return -1;
}
return 0;
case SIOLISTEN:
if (info->type != LISTENER_MAGIC) {
errno = ENOTSOCK;
return -1;
}
info->pcb = tcp_listen (info->pcb);
info->d.listener.listener_queue_max_len = *config;
tcp_arg (info->pcb, o);
tcp_accept (info->pcb, _socket_accept);
return 0;
}
errno = EINVAL;
return -1;
}
static void *socket_accept (void *o, struct sockaddr *addr, int *addrlen)
{
incoming_item *j;
struct socket_info *info, *linfo = (struct socket_info *) o;
if (linfo->type != LISTENER_MAGIC) {
errno = ENOTSOCK;
return 0;
}
if (*addrlen != sizeof (struct sockaddr_in)) {
errno = EFAULT;
return 0;
}
j = lhead (linfo->d.listener.incoming_list);
if (!j) {
errno = EAGAIN;
return 0;
}
info = (struct socket_info *) malloc (sizeof (struct socket_info));
if (!info) {
errno = ENOMEM;
return 0;
}
memset (info, 0, sizeof (struct socket_info));
info->type = STREAM_MAGIC;
linit (info->d.stream.packet_list, packet_item, packet_free);
info->pcb = j->pcb;
j->pcb = 0; /* set to zero so it doesn't free */
/* remove from listener queue */
ldeleteinc (linfo->d.listener.incoming_list, j);
tcp_arg (info->pcb, (void *) info);
tcp_recv (info->pcb, _socket_recv);
tcp_err (info->pcb, _socket_error);
tcp_poll (info->pcb, _socket_poll, 4);
return (void *) info;
}
struct file file_socket = {
socket_socket, /* we use the open() method */
socket_dup,
socket_close,
socket_ioctl,
0,
socket_write,
socket_write,
socket_write_space,
socket_write_nonblock,
0,
socket_read,
socket_read,
socket_read_avail,
socket_read_nonblock,
socket_write_queue,
0,
0,
socket_accept,
};
---------------------------------------------
This message was sent using World Mail.
http://www.worldonline.co.za
[This message was sent through the lwip discussion list.]
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lwip-users] [lwip] lwIP crashing after 17MB of data transfer,
psheer <=