Speicher Leak lwip netconn

OP #4547647
Lesenswert?

Hi,

ich habe ein Problem mit meinem lwip. Nachdem ca. 5-6 mal ein request 
verarbeitet wurde, bleibt der controller stehen - ich lande in der _sbrk 
function (Heap <=> Stack Kollision).

In der 'serve' function reserviere ich selbst doch gar keinen speicher. 
Passiert doch alles auf dem Stack. Klar lwip - der netbuf - aber der 
wird ja unten ueber netbuf_delete(inbuf) wieder freigegeben.

Bezueglich Heap Speicher mit free freigeben stellt sich mir allerdings 
die Frage wie das gehen soll. Der HeapPointer wird doch immer weiter 
hoch geschoben. Egal ob free irgendwas davor freigibt, ein weiteres 
reservieren schiebt den HeapPointer immer weiter oder nicht?

1
    #include <HttpServer.h>
2

3
    const static char http_html_hdr[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
4
    const static char http_index_html[] = "<html><head><title>Congrats!</title></head><body><h1>Welcome to our lwIP HTTP server!</h1><p>This is a small test page, served by httpserver-netconn.</body></html>";
5

6
    HttpServer::HttpServer(ip_addr *address, uint16_t port) :
7
                    address(address), port(port) {
8

9
    }
10

11
    void HttpServer::schedule() {
12

13
            char buf[16];
14
            sprintf(taskName, "HttpServer_%s_%d", ipaddr_ntoa_r(address, buf, 16), port);
15
            DEBUGOUT("[TASK] Listen Address: %s Port: %d\r\n", ipaddr_ntoa_r(address, buf, 16), port);
16

17
            this->handle = sys_thread_new(this->taskName, &taskfun, this, 512, DEFAULT_THREAD_PRIO);
18

19
    }
20

21
    void HttpServer::run() {
22

23
            struct netconn *conn, *newconn;
24
            err_t err;
25

26
            try {
27

28
                    /* Create a new TCP connection handle */
29
                    conn = netconn_new(NETCONN_TCP);
30
                    if (conn == NULL) {
31
                            throw InvalidNetConn;
32
                    }
33

34
                    /* Bind to port 80 (HTTP) with default IP address */
35
                    netconn_bind(conn, this->address, this->port);
36

37
                    /* Put the connection into LISTEN state */
38
                    netconn_listen(conn);
39

40
                    do {
41

42
                            err = netconn_accept(conn, &newconn);
43
                            if (err == ERR_OK) {
44
                                    this->serve(newconn);
45
                                    netconn_delete(newconn);
46
                            }
47

48
                    } while (err == ERR_OK);
49

50
                    LWIP_DEBUGF(HTTPD_DEBUG, ("http_server_netconn_thread: netconn_accept received error %d, shutting down", err));
51

52
            } catch (int error) {
53

54
                    switch (error) {
55
                    case InvalidNetConn:
56
                            LWIP_DEBUGF(HTTPD_DEBUG, ("http_server_netconn_thread: Invalid NetConn, shutting down"));
57
                            break;
58
                    }
59

60
            }
61

62
            netconn_close(conn);
63
            netconn_delete(conn);
64

65
    }
66

67
    void HttpServer::serve(struct netconn *conn) {
68

69
            struct netbuf *inbuf;
70
            char *buf, *tbuf;
71
            u16_t buflen;
72
            err_t err;
73

74
            /* Read the data from the port, blocking if nothing yet there.
75
            We assume the request (the part we care about) is in one netbuf */
76
            err = netconn_recv(conn, &inbuf);
77

78
            if (err != ERR_OK) {
79
                    return;
80
            }
81

82
            try {
83

84
                    netbuf_data(inbuf, (void**) &buf, &buflen);
85

86
                    netconn_write(conn, http_html_hdr, sizeof(http_html_hdr) - 1, NETCONN_NOCOPY);
87
                    netconn_write(conn, http_index_html, sizeof(http_index_html) - 1, NETCONN_NOCOPY);
88

89
                    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("HTTPD: Got URI %s\r\n", buf));
90

91
            } catch (int error) {
92

93
                    switch (error) {
94
                    case InvalidRequest:
95
                            LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Invalid Request Line\r\n"));
96
                            break;
97
                    }
98

99
            }
100

101
            /* Close the connection (server closes in HTTP) */
102
            netconn_close(conn);
103

104
            /* Delete the buffer (netconn_recv gives us ownership,
105
            so we have to make sure to deallocate the buffer) */
106
            netbuf_delete(inbuf);
107

108
    }
109

110
    HttpServer::~HttpServer() {
111
            // TODO Auto-generated destructor stub
112
    }
113

114
    caddr_t _sbrk(int incr) {
115

116
            if (heap_ptr + incr < (void*) __get_MSP()) {
117

118
                    caddr_t base = heap_ptr;
119
                    heap_ptr += incr;
120

121
                    return base;
122

123
            } else {
124

125
                    errno = ENOMEM;
126
                    return (caddr_t) -1;
127

128
            }
129

130
    }
OP #4547893
Lesenswert?

Also wenn ich _sbrk mit einem breakpoint versehe, ist incr immer 
positiv, nie negativ.

Ist folgendes Beispiel falsch?
Der HeapPointer wird immer weiter geschoben, was passiert mit dem 
freigegebenen Speicher von ptr_m? Kuemmert sich newlib nano darum diesen 
Speicher wieder zu verwenden? Bei mir scheint das nicht der fall zu 
sein.

                             HeapPointer
HeapStart                    0x10000000
malloc->_sbrk(1000) ptr_m    0x10001000
malloc->_sbrk(1000) ptr_n    0x10002000
free(ptr_m)                  0x10002000
malloc->_sbrk(1000) ptr_k    0x10003000
OP #4548182
Lesenswert?

In welche Richtung?

Wenn ich MEM_SIZE erhoehe laeuft RTOS gar nicht los.

1
#define configMINIMAL_STACK_SIZE  ( ( unsigned short ) 128 )
2
#define MEM_SIZE                        (12 * 1024)
3

4
#define DEFAULT_THREAD_STACKSIZE        (configMINIMAL_STACK_SIZE)
5
#define TCPIP_THREAD_STACKSIZE          (configMINIMAL_STACK_SIZE + 256)
Gast #4548238
Lesenswert?

Pascal H. schrieb:
> In welche Richtung?

Hängt von der Hardware ab. Ich hab STM32F7 und aase ein wenig der 
Stabilität zu liebe.
#define DEFAULT_THREAD_STACKSIZE    512
#define TCPIP_THREAD_STACKSIZE      1536
#define MEM_SIZE                        (24*1024)

#define PBUF_POOL_SIZE                  20
#define PBUF_POOL_BUFSIZE               1524

#define MEMP_NUM_PBUF                   50
#define MEMP_NUM_UDP_PCB                10
#define MEMP_NUM_TCP_PCB                20
#define MEMP_NUM_TCP_PCB_LISTEN         20

Ich musste fürs debuggen erhöhen da kommen ja noch Printaufrufe dazu.
Das gibt so 100 Kilo Ram aber ich hab ja 320.Und da ist auch noch mein 
Webserver mit drin der 10 Threads für sich braucht.
OP #4548329
Lesenswert?

Ich hab einen lpc1768 mit 32k RAM.

Diese Function wird bei jedem request aufgerufen. Ich gebe da den 
heapPointer aus. Komischerweise schiebt sich der nicht immer weiter aber 
nach 5-6 request erhoeht er sich immer.

Und nach ca 20 request gibt meine sbrk 0 zurueck da ich bei __get_MSP() 
angelangt bin.

Ich verstehe nicht warum immer mehr heap reserviert wird.

Auch wenn ich nicht sprintf verwende und als body
1
const static char http_index_html[] = "<html><head><title>lwip netconn</title></head><body><h1>Heap Pointer: </h1></body></html>";
2

3
...
4

5
netconn_write(conn, http_index_html, sizeof(http_index_html) - 1, NETCONN_NOCOPY);

verwende passiert das gleiche, der controller steht.
1
void HttpServer::serve(struct netconn *conn) {
2

3
  struct netbuf *inbuf;
4
  char *buf, *tbuf;
5
  u16_t buflen;
6
  err_t err;
7

8
  /* Read the data from the port, blocking if nothing yet there.
9
   We assume the request (the part we care about) is in one netbuf */
10
  err = netconn_recv(conn, &inbuf);
11

12
  if (err != ERR_OK) {
13
    return;
14
  }
15

16
  try {
17

18
    netbuf_data(inbuf, (void**) &buf, &buflen);
19

20
    char buffer[98];
21
    sprintf(buffer, "<html><head><title>lwip netconn</title></head><body><h1>Heap Pointer: %x</h1></body></html>\0", getHeapPointer());
22

23
    netconn_write(conn, http_html_hdr, sizeof(http_html_hdr) - 1, NETCONN_NOCOPY);
24
    netconn_write(conn, buffer, sizeof(buffer) - 1, NETCONN_COPY);
25

26
    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("HTTPD: Got URI %s\r\n", buf));
27

28
  } catch (int error) {
29

30
    switch (error) {
31
    case InvalidRequest:
32
      LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Invalid Request Line\r\n"));
33
      break;
34
    }
35

36
  }
37

38
  /* Close the connection (server closes in HTTP) */
39
  netconn_close(conn);
40

41
  /* Delete the buffer (netconn_recv gives us ownership,
42
   so we have to make sure to deallocate the buffer) */
43
  netbuf_delete(inbuf);
44

45
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren