As the title says... Chat on...

User avatar
By dnc40085
#14809
TerryE wrote:The problem is your function listap. It's not a local function so the name is registered in the globals table, and therefore the memory for the code and function headers can't be garbage collected. If you have Lua installed on your PC, then you can do a luac -l of the dofile code to see what is generated.

If you want resources GCed, then declare them local.

Avoid writing stuff to flash, because it has a limited write life. If you do want to write configuration data to flash then at least check that it's changed before writing it. I know this is two pass, but your esp8266 will last a lot longer if you adopt this strategy.


Hello TerryE,
At first I thought it was an issue with it not being available for garbage collection so I tried just declaring the function and then setting it to nil and I got most of my memory back minus 272 bytes so I tried adding local to the declaration and got it all back. I then decided to test it out with wifi.sta.getap() back in CheckAP.lua...

I changed the CheckAp.lua to:
Code: Select alllocal listap= function(t)
    if type(t)~="table" then
        print("not table")
        return
    end
    for key,value in pairs(t) do
        tmr.wdclr()
        --if string.find(key , "myssid") then
            local _SSID = key
            local _BSSID=""
            local _RSSI=""
            local _enc=""
            local _chan=""
            _enc, _RSSI, _BSSID, _chan = string.match(value,
                "(%d),(-?%d+),(%x%x:%x%x:%x%x:%x%x:%x%x:%x%x),(%d+)")
            print(_SSID..":\t\t".._BSSID..",".._RSSI.."\n")
            _enc=nil _chan=nil
            _SSID=nil _RSSI=nil _BSSID=nil
           
        --end
    end
end
wifi.setmode(wifi.STATION)
wifi.sta.getap(listap)
listap=nil


and the result was as follows
Code: Select all=node.heap()
20256
> dofile("CheckAP.lua")
>myssid:      1a:fe:34:xx:xx:xx,-1

xfinitywifi:      96:1a:ca:xx:xx:xx,-91

Linksys_dd-wrt:      00:1d:7e:xx:xx:xx,-64

=node.heap()
17952
>

I observed that the addition of local to the listap function brought the memory use from 2528 bytes down to 2272 used by the execution of CheckAP.lua, but didn't solve the memory use issue so then I thought it might be that the wifi.sta.getap() function is not releasing the memory. so i then copied the contents CheckAP.lua to a new file to test with named listap_test.lua and modified it.
listap_test.lua:
Code: Select alllocal T={}
    T["myssid"]="4,-12,13:37:13:37:13:37,6"
    T["MadeUpAP_1"]="4,-38,1A:3B:BE:EF:42:62,6"
    T["MadeUpAP_2"]="4,-42,80:08:80:08:80:08,6"
    T["MadeUpAP_3"]="4,-42,01:55:58:67:53:09,6"
   
local listap= function(t)
    if type(t)~="table" then
        print("not table")
        return
    end
    for key,value in pairs(t) do
        tmr.wdclr()
        --if string.find(key , "myssid") then
            local _SSID = key
            local _BSSID=""
            local _RSSI=""
            local _enc=""
            local _chan=""
            _enc, _RSSI, _BSSID, _chan = string.match(value,
                "(%d),(-?%d+),(%x%x:%x%x:%x%x:%x%x:%x%x:%x%x),(%d+)")
            print(_SSID..":\t\t".._BSSID..",".._RSSI.."\n")
            _enc=nil _chan=nil
            _SSID=nil _RSSI=nil _BSSID=nil
        --end
    end
end
listap(T)
listap=nil
T=nil


The result of this test was:
Code: Select all=node.heap()
20256
> dofile("listap_test.lua")
myssid:      13:37:13:37:13:37,-12

MadeUpAP_3:      01:55:58:67:53:09,-42

MadeUpAP_1:      1A:3B:BE:EF:42:62,-38

MadeUpAP_2:      80:08:80:08:80:08,-42

> =node.heap()
20088
>

I found that my memory use had drastically reduced from 2272 to 168 bytes after running the modified version (listap_test.lua). which brings me to the conclusion that the issue must be in the wifi.sta.getap() function.
As for a workaround for this issue to get the memory back I have no idea where to start whether it be in my lua script or in the nodemcu source code.

Maybe I need to post this in the issues section of the nodemcu github...
User avatar
By TerryE
#14811 Thanks and interesting. If you think that the leak is in the wifi.sta.getap() function, then why not have a look at the source?
User avatar
By dnc40085
#14882
cal wrote:Moin,

does

Code: Select allwifi.sta.getap(nil)


change something?

Carsten


It worked! kinda.

CheckAP.lua:
Code: Select alllocal listap= function(t)
    if type(t)~="table" then
        print("Not A Table")
        _SSID=NotATable
        tmr.wdclr()
        wifi.sta.getap(function() return end)
        return --wifi.sta.getap(listap)
    end
    for key,value in pairs(t) do
        tmr.wdclr()
            local _SSID = key
            local _BSSID=""
            local _RSSI=""
            local _enc=""
            local _chan=""
            _enc, _RSSI, _BSSID, _chan = string.match(value,
                "(%d),(-?%d+),(%x%x:%x%x:%x%x:%x%x:%x%x:%x%x),(%d+)")
            print(_SSID..":\t\t".._BSSID..",".._RSSI.."\n")
            _enc=nil _chan=nil
            _SSID=nil _RSSI=nil _BSSID=nil
    end
    wifi.sta.getap(function() return end)
end
wifi.setmode(wifi.STATION)
wifi.sta.getap(listap)
listap=nil


result:
Code: Select all=node.heap()
18880
> dofile("CheckAP.lua")
>
Linksys_dd-wrt:      00:1d:7e:XX:XX:XX,-51

myssid:      1a:fe:34:XX:XX:XX,-1

xfinitywifi:      c6:27:95:XX:XX:XX,-43

=node.heap()
18424

Looks like adding in "wifi.sta.getap(function() return end)" brought it down around 500 bytes which is much more manageable than before. Thank you for your suggestion cal.


TerryE wrote:Thanks and interesting. If you think that the leak is in the wifi.sta.getap() function, then why not have a look at the source?


My experience in the C language is limited to what little I've learned via the Arduino platform, so that may prove troublesome. but that's not gonna stop me from trying.
i'm gonna start by taking a look at the source for wifi.sta.getap() in the file app/modules/wifi.c and hopefully, using the ESP8266 Espressif IoT SDK Programming Guide( page 27, section 3.4.8) I can decipher the function so I can attempt to find the memory leak.

If anyone wants to join the fun, feel free.
Code: Select allstatic int wifi_scan_succeed = LUA_NOREF;
static lua_State* gL = NULL;
/**
  * @brief  Wifi ap scan over callback to display.
  * @param  arg: contain the aps information
  * @param  status: scan over status
  * @retval None
  */
static void wifi_scan_done(void *arg, STATUS status)
{
  uint8 ssid[33];
  char temp[128];
  if(wifi_scan_succeed == LUA_NOREF)
    return;
  if(arg == NULL)
    return;
 
  lua_rawgeti(gL, LUA_REGISTRYINDEX, wifi_scan_succeed);

  if (status == OK)
  {
    struct bss_info *bss_link = (struct bss_info *)arg;
    bss_link = bss_link->next.stqe_next;//ignore first
    lua_newtable( gL );

    while (bss_link != NULL)
    {
      c_memset(ssid, 0, 33);
      if (c_strlen(bss_link->ssid) <= 32)
      {
        c_memcpy(ssid, bss_link->ssid, c_strlen(bss_link->ssid));
      }
      else
      {
        c_memcpy(ssid, bss_link->ssid, 32);
      }
      c_sprintf(temp,"%d,%d,"MACSTR",%d", bss_link->authmode, bss_link->rssi,
                 MAC2STR(bss_link->bssid),bss_link->channel);

      lua_pushstring(gL, temp);
      lua_setfield( gL, -2, ssid );

      // NODE_DBG(temp);

      bss_link = bss_link->next.stqe_next;
    }
  }
  else
  {
    lua_pushnil(gL);
  }
  lua_call(gL, 1, 0);
}

static int wifi_station_listap( lua_State* L )
{
  if(wifi_get_opmode() == SOFTAP_MODE)
  {
    return luaL_error( L, "Can't list ap in SOFTAP mode" );
  }
  gL = L;
  // luaL_checkanyfunction(L, 1);
  if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION){
    lua_pushvalue(L, 1);  // copy argument (func) to the top of stack
    if(wifi_scan_succeed != LUA_NOREF)
      luaL_unref(L, LUA_REGISTRYINDEX, wifi_scan_succeed);
    wifi_scan_succeed = luaL_ref(L, LUA_REGISTRYINDEX);
    wifi_station_scan(NULL,wifi_scan_done);
  } else {
    if(wifi_scan_succeed != LUA_NOREF)
      luaL_unref(L, LUA_REGISTRYINDEX, wifi_scan_succeed);
    wifi_scan_succeed = LUA_NOREF;
  }
}


Found via Google
(1.83 MiB) Downloaded 428 times