diff options
-rw-r--r-- | bin/lem.c | 56 | ||||
-rw-r--r-- | include/lem.h | 6 | ||||
-rw-r--r-- | lem/io.lua | 5 | ||||
-rw-r--r-- | lem/io/core.c | 23 | ||||
-rw-r--r-- | lem/io/file.c | 7 | ||||
-rw-r--r-- | lem/io/stream.c | 7 | ||||
-rw-r--r-- | lem/signal/core.c | 3 |
7 files changed, 104 insertions, 3 deletions
@@ -37,7 +37,7 @@ #endif #ifdef NDEBUG -#define lem_log_error(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#define lem_log_error(fmt, ...) lem_dprintf(STDERR_FILENO, fmt "\n", ##__VA_ARGS__) #else #define lem_log_error lem_debug #endif @@ -69,6 +69,7 @@ static lua_State *L; static struct lem_runqueue rq; static int exit_status = EXIT_SUCCESS; +__attribute__((noreturn)) static void oom(void) { @@ -93,6 +94,59 @@ lem_xmalloc(size_t size) return p; } +/* non-blocking tolerant version of dprintf(3) */ +void +lem_dprintf(int fd, const char *fmt, ...) +{ + int size = 0; + char *p = NULL; + va_list ap; + char *pos; + ssize_t ret; + size_t bytes_left; + + /* Determine required size */ + va_start(ap, fmt); + size = vsnprintf(p, size, fmt, ap); + va_end(ap); + + if (size < 0) + return; + + size++; /* for '\0' */ + p = lem_xmalloc(size); + if (p == NULL) + return; + + va_start(ap, fmt); + size = vsnprintf(p, size, fmt, ap); + va_end(ap); + + if (size < 0) { + free(p); + return; + } + + pos = p; + bytes_left = size; + while (bytes_left > 0) { + ret = write(fd, pos, bytes_left); + if (ret == -1) { + /* since this function is only used for debug messages + * we prefer sleeping, over missing debug messages */ + if (errno == EAGAIN || errno == EINTR) { + usleep(100); + continue; + } + break; + } else { + pos += ret; + bytes_left -= ret; + } + } + free(p); +} + static int setsignal(int signal, void (*handler)(int), int flags) { diff --git a/include/lem.h b/include/lem.h index 2b548b8..9277c3e 100644 --- a/include/lem.h +++ b/include/lem.h @@ -22,6 +22,7 @@ #include <ev.h> #include <lua.h> #include <lauxlib.h> +#include <unistd.h> /* Support gcc's __FUNCTION__ for people using other compilers */ #if !defined(__GNUC__) && !defined(__FUNCTION__) @@ -38,9 +39,9 @@ #define lem_debug(...) #else #define lem_debug(fmt, ...) do { \ - printf("%s (%s:%u): " fmt "\n", \ + lem_dprintf(STDOUT_FILENO, "%s (%s:%u): " fmt "\n", \ __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ - fflush(stdout); } while (0) + } while (0) #endif #if EV_MINPRI == EV_MAXPRI @@ -72,6 +73,7 @@ void lem_queue(lua_State *T, int nargs); void lem_exit(int status); void lem_async_run(struct lem_async *a); void lem_async_config(int delay, int min, int max); +void lem_dprintf(int fd, const char *format, ...); static inline void lem_async_do(struct lem_async *a, @@ -76,6 +76,11 @@ do return stdout:write(...) end + function io.print(...) + return stdout:print(...) + end + _ENV.print = io.print + function io.close(file) if not file then file = stdout end return file:close() diff --git a/lem/io/core.c b/lem/io/core.c index 4844bac..5917b64 100644 --- a/lem/io/core.c +++ b/lem/io/core.c @@ -104,6 +104,23 @@ error: return luaL_argerror(T, idx, "invalid permissions"); } +static void +io_print(lua_State *T) +{ + int orig_top = lua_gettop(T); + luaL_checktype(T, 1, LUA_TUSERDATA); + lua_checkstack(T, (orig_top - 1) * 3 + 1); + for (int i=2;i<=orig_top;i++) { + if (i>2) lua_pushliteral(T, "\t"); + (void)luaL_tolstring(T, i, NULL); + } + lua_pushliteral(T, "\n"); + if (orig_top > 1) { + lua_rotate(T, 2, 1 - orig_top); + lua_settop(T, (orig_top - 1) * 2 + 1); + } +} + #include "file.c" #include "stream.c" #include "server.c" @@ -600,6 +617,9 @@ luaopen_lem_io_core(lua_State *L) /* mt.lock = <file_lock> */ lua_pushcfunction(L, file_lock); lua_setfield(L, -2, "lock"); + /* mt.print = <file_print> */ + lua_pushcfunction(L, file_print); + lua_setfield(L, -2, "print"); /* insert table */ lua_setfield(L, -2, "File"); @@ -637,6 +657,9 @@ luaopen_lem_io_core(lua_State *L) /* mt.sendfile = <stream_sendfile> */ lua_pushcfunction(L, stream_sendfile); lua_setfield(L, -2, "sendfile"); + /* mt.print = <stream_print> */ + lua_pushcfunction(L, stream_print); + lua_setfield(L, -2, "print"); /* insert io.stdin stream */ push_stdstream(L, STDIN_FILENO); lua_setfield(L, -3, "stdin"); diff --git a/lem/io/file.c b/lem/io/file.c index 9d54fcb..347414a 100644 --- a/lem/io/file.c +++ b/lem/io/file.c @@ -519,3 +519,10 @@ file_lock(lua_State *T) lua_settop(T, 1); return lua_yield(T, 1); } + +static int +file_print(lua_State *T) +{ + io_print(T); + return file_write(T); +} diff --git a/lem/io/stream.c b/lem/io/stream.c index 47a5775..db23e91 100644 --- a/lem/io/stream.c +++ b/lem/io/stream.c @@ -559,3 +559,10 @@ stream_sendfile(lua_State *T) lua_settop(T, 2); return lua_yield(T, 2); } + +static int +stream_print(lua_State *T) +{ + io_print(T); + return stream_write(T); +} diff --git a/lem/signal/core.c b/lem/signal/core.c index 695f9d6..683db89 100644 --- a/lem/signal/core.c +++ b/lem/signal/core.c @@ -96,7 +96,10 @@ signal_os_watch(lua_State *T, int sig) s = lem_xmalloc(sizeof(struct sigwatcher)); signal_watcher_init(s, sig); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" ev_set_priority(&s->w, EV_MAXPRI); +#pragma GCC diagnostic pop ev_signal_start(LEM_ &s->w); ev_unref(LEM); /* watcher shouldn't keep loop alive */ |