I finally have a minimal working version and it has nothing to do with luasql.postgres. It does come down to my little extension:
/*
* gcc -Wall -shared -fPIC -o time_now.so -llua time_now.c
*
* This is an unusual case. I need the current time, down to microseconds,
* as a string for things like logs. Not something that Lua is good at.
*/
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include <stdio.h>
#include <sys/time.h>
#define BUFFER_SIZE 64
#define LENGTH_OF_DATE_TIME 19
#define LENGTH_OF_MS 8
static int time_now (lua_State *L) {
char buffer[BUFFER_SIZE];
struct tm* tm_info;
struct timeval tv;
long int ms;
gettimeofday(&tv, NULL);
tm_info = localtime(&tv.tv_sec);
strftime(buffer, BUFFER_SIZE, "%Y-%m-%dT%H:%M:%S", tm_info);
ms = (long int)tv.tv_usec % 1000000;
snprintf(buffer + LENGTH_OF_DATE_TIME, LENGTH_OF_MS, ".%06ld", ms);
lua_pushstring(L, buffer);
return 1;
}
int luaopen_time_now(lua_State *L){
lua_register(L, "time_now", time_now);
return 0;
}
With the following test program:
require 'time_now'
local function build()
local t = {}
for i = 1,10000 do
t[i] = time_now()
end
end
local counter = 0
while true do
counter = counter + 1
print("Iteration " .. counter)
build()
end
The program will consistently crash thus:
Iteration 1
Iteration 2
Iteration 3
lua(5965,0x7fff7ab92000) malloc: *** error for object 0x10001f6c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
There are two work arounds, first is to kick the garbage collector:
local function build()
collectgarbage()
local t = {}
for i = 1,10000 do
t[i] = time_now()
end
end
or simply force some output:
local function build()
local t = {}
for i = 1,10000 do
print(i)
t[i] = time_now()
end
end
Both of these changes will allow the process to run forever. However it is a pain to say "when using time_now() you need to stick a collectgarbage() somewhere".
Is there something I can do to my extension to avoid this problem as it feels a little to voodoo to have to stick a collectgarbage() at some random point in the program or end up calling it every time I call time_now()
A good place to insert collectgarbage() today may not be a good place tomorrow :(