summaryrefslogtreecommitdiffstats
path: root/bin/lem.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/lem.c')
-rw-r--r--bin/lem.c56
1 files changed, 55 insertions, 1 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)
{