LWIP зависает через некоторое время из-за не освобождения памяти - PullRequest
1 голос
/ 28 марта 2019

OBS: я использую микроконтроллер STM32F2, FreeRTOS и lwIP и использую raw API

У меня есть приложение, в котором я слушаю один компьютер и подключаюсь к другому.В основном все работает некоторое время, когда я пытаюсь достичь высокой пропускной способности, но примерно через полчаса ... около 80 ~ 90 тыс. Полученных пакетов зависает.На самом деле он немного меняется в зависимости от того, где он висит, но он перестал это делать, когда я начал закрывать соединение всякий раз, когда tcp_write возвращал err_mem.

Иногда он зависает в этой строке:

/* useg should point to last segment on unacked queue */

  useg = pcb->unacked;

  if (useg != NULL) {

    for (; useg->next != NULL; useg = useg->next);  <------- here

  }

Иногда, когда я вызываю tcp_write, он возвращает ERR_MEM и никогда не возвращает ничего, кроме после ERR_MEM.Вот как я отправляю данные, в основном я принимаю соединение, получаю данные, сохраняю PCB, делаю что-то и затем отвечаю на ту же самую PCB:

err_t ret;
ret = tcp_write(g_response[i].pcb, data, len, 1);
if(ret == ERR_OK)
    tcp_output(g_response[i].pcb);
else
    tcp_close(g_response[i].pcb);

Вот как я настраиваю сокет для прослушивания:

pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, port);
pcb = tcp_listen(pcb);
pcb->so_options |= SOF_KEEPALIVE; // enable keep-alive
pcb->keep_intvl = 1000; // sends keep-alive every second
tcp_accept(pcb, accept);

А вот мои обратные вызовы отправленным и rcv

static err_t rcv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
    if(p == NULL) {
        return ERR_OK;
    } else if(err != ERR_OK) {
        return err;
    }

    tcp_recved(pcb, p->len);
    // do something

    pbuf_free(p);

    return ERR_OK;
}

int sentcounter = 0;
static err_t sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {

    sentcounter++;
    return ERR_OK;
}

static err_t accept(void *arg, struct tcp_pcb *pcb, err_t err) {
    int i;
    tcp_arg(pcb, NULL);
    /* Set up the various callback functions */
    tcp_recv(pcb, rcv);
    tcp_err(pcb, error);
    tcp_sent(pcb, sent);

    tcp_accepted(pcb);
}

Способ отправки данных, когда я закрываю печатную плату всякий раз, когда отсутствует ERR_MEM, может быть странным, но теперь я потерял меньшепакеты, и это фактически заставило меня обмениваться до 90 тыс. пакетов, до этого это происходило случайным образом.

Мне действительно нужна высокая пропускная способность, поэтому я вызываю tcp_output вместо того, чтобы позволить tcpip_thread иметь дело с отправкой пакета.Всякий раз, когда я позволяю этому потоку взять машину из пакета, все работает, но это слишком медленно (возможно, один пакет каждые 200 ~ 300 мс, и, вызвав tcp_output в функции, я дошел до точки, куда я отправляю подпрограмму данных 10 мс... Я также не передаю большие объемы данных, так что это помогает).

Недавно я заметил, что tcpip_thread вызывает функцию ввода, переходит к ipv4_input, переходит к memp_free и продолжает работу, но никогда не уходит (на самом деле я сейчас запускаю новый тест, поэтому позже я обновлю этовопрос с callstack на вход, прежде чем он зависает).

Кто-нибудь делал что-нибудь подобное?Пакеты небольших пакетов с высокой пропускной способностью?

РЕДАКТИРОВАТЬ: Как и было обещано, вот мой стек вызовов

osMutexWait () в cmsis_os.c: 681 0x800474c sys_arch_protect () в

sys_arch.c: 400 0x80146a6 do_memp_free_pool () в memp.c: 415 0x800dca2

memp_free () в memp.c: 486 0x800dcf8 tcp_seg_free () в tcp.c: 1.006 * 0e0b03434() в tcp_in.c: 1.162 0x8011712 tcp_process () в

tcp_in.c: 877 0x8011048 tcp_input () в tcp_in.c: 367 0x8010692

ip4_input () в ip4_inc0x800c688 ethernet_input () в ethernet.c: 176

0x80142fe tcpip_thread () в tcpip.c: 124 0x8006836

pxPortInitialiseStack () в port.c: 231 0x8004c451046 * Точно так же, как сказал @Lundin, это проблема параллелизма.Я, вероятно, должен попытаться быть более осторожным с тем, как называются функции.Я попытаюсь изменить свой код для работы с netconn или сокетом вместо tcp_pcb, а затем измерить скорости, которые я получаю.Мне действительно нужна высокая пропускная способность

...