summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/lem.c56
-rw-r--r--include/lem.h6
-rw-r--r--lem/io.lua5
-rw-r--r--lem/io/core.c23
-rw-r--r--lem/io/file.c7
-rw-r--r--lem/io/stream.c7
-rw-r--r--lem/signal/core.c3
7 files changed, 104 insertions, 3 deletions
diff --git a/bin/lem.c b/bin/lem.c
index d1f9747..433849d 100644
--- a/bin/lem.c
+++ b/bin/lem.c
@@ -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,
diff --git a/lem/io.lua b/lem/io.lua
index bd24d66..9972b37 100644
--- a/lem/io.lua
+++ b/lem/io.lua
@@ -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 */