lua-bindings: added Lua bindings for murphy sighandlers.
authorKrisztian Litkey <kli@iki.fi>
Mon, 11 Nov 2013 02:23:07 +0000 (04:23 +0200)
committerKrisztian Litkey <kli@iki.fi>
Mon, 11 Nov 2013 20:22:09 +0000 (22:22 +0200)
src/Makefile.am
src/core/lua-bindings/lua-sighandler.c [new file with mode: 0644]

index 703ffe7..0686b12 100644 (file)
@@ -263,7 +263,8 @@ LUA_BINDINGS_SOURCES =                                      \
                core/lua-bindings/lua-console.c         \
                core/lua-bindings/lua-json.c            \
                core/lua-bindings/lua-timer.c           \
-               core/lua-bindings/lua-deferred.c
+               core/lua-bindings/lua-deferred.c        \
+               core/lua-bindings/lua-sighandler.c
 
 libmurphy_core_lua_bindings_ladir =                    \
                $(includedir)/murphy/core/lua-bindings
diff --git a/src/core/lua-bindings/lua-sighandler.c b/src/core/lua-bindings/lua-sighandler.c
new file mode 100644 (file)
index 0000000..64c5e8a
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012, 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <murphy/common/macros.h>
+#include <murphy/common/debug.h>
+#include <murphy/common/log.h>
+#include <murphy/common/mm.h>
+#include <murphy/common/mainloop.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+#include <murphy/core/lua-bindings/murphy.h>
+
+#define SIGHANDLER_LUA_CLASS MRP_LUA_CLASS(sighandler, lua)
+
+/*
+ * Lua sighandler object
+ */
+
+typedef struct {
+    lua_State        *L;                 /* Lua execution context */
+    mrp_sighandler_t *h;                 /* associated murphy sighandler */
+    int               signum;            /* signal number */
+    int               callback;          /* reference to callback */
+    int               data;              /* referece to callback data */
+    bool              oneshot;           /* true for one-shot sighandlers */
+} sighandler_lua_t;
+
+
+static int sighandler_lua_create(lua_State *L);
+static void sighandler_lua_destroy(void *data);
+static int sighandler_lua_stringify(lua_State *L);
+static void sighandler_lua_changed(void *data, lua_State *L, int member);
+
+
+/*
+ * Lua sighandler class
+ */
+
+#define OFFS(m) MRP_OFFSET(sighandler_lua_t, m)
+#define RDONLY  MRP_LUA_CLASS_READONLY
+#define NOTIFY  MRP_LUA_CLASS_NOTIFY
+#define NOFLAGS MRP_LUA_CLASS_NOFLAGS
+
+MRP_LUA_METHOD_LIST_TABLE(sighandler_lua_methods,
+                          MRP_LUA_METHOD_CONSTRUCTOR(sighandler_lua_create));
+
+MRP_LUA_METHOD_LIST_TABLE(sighandler_lua_overrides,
+                          MRP_LUA_OVERRIDE_CALL     (sighandler_lua_create)
+                          MRP_LUA_OVERRIDE_STRINGIFY(sighandler_lua_stringify));
+
+MRP_LUA_MEMBER_LIST_TABLE(sighandler_lua_members,
+    MRP_LUA_CLASS_INTEGER("signal"   , OFFS(signum)   , NULL, NULL, RDONLY )
+    MRP_LUA_CLASS_LFUNC  ("callback" , OFFS(callback) , NULL, NULL, NOFLAGS)
+    MRP_LUA_CLASS_ANY    ("data"     , OFFS(data)     , NULL, NULL, NOFLAGS)
+    MRP_LUA_CLASS_BOOLEAN("oneshot"  , OFFS(oneshot)  , NULL, NULL, NOFLAGS));
+
+typedef enum {
+    SIGHANDLER_MEMBER_SIGNAL,
+    SIGHANDLER_MEMBER_CALLBACK,
+    SIGHANDLER_MEMBER_DATA,
+    SIGHANDLER_MEMBER_DISABLED,
+    SIGHANDLER_MEMBER_ONESHOT,
+} sighandler_member_t;
+
+MRP_LUA_CLASS_DEF_MEMBERS(sighandler, lua, sighandler_lua_t,
+                          sighandler_lua_destroy, sighandler_lua_methods,
+                          sighandler_lua_overrides, sighandler_lua_members,
+                          NULL, sighandler_lua_changed,
+                          MRP_LUA_CLASS_EXTENSIBLE);
+
+
+static void sighandler_lua_cb(mrp_sighandler_t *hlr, int sig, void *user_data)
+{
+    sighandler_lua_t *h   = (sighandler_lua_t *)user_data;
+    int               one = h->oneshot;
+    const char       *s   = strsignal(sig);
+
+    MRP_UNUSED(hlr);
+
+    if (mrp_lua_object_deref_value(h, h->L, h->callback, false)) {
+        mrp_lua_push_object(h->L, h);
+        if (s != NULL)
+            lua_pushstring(h->L, s);
+        else
+            lua_pushinteger(h->L, sig);
+        mrp_lua_object_deref_value(h, h->L, h->data, true);
+
+        if (lua_pcall(h->L, 2, 0, 0) != 0)
+            mrp_log_error("failed to invoke Lua sighandler callback");
+    }
+
+    if (one)
+        mrp_del_sighandler(h->h);
+}
+
+
+static void sighandler_lua_changed(void *data, lua_State *L, int member)
+{
+    sighandler_lua_t *h = (sighandler_lua_t *)data;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(h);
+
+    mrp_debug("sighandler member #%d (%s) changed", member,
+              sighandler_lua_members[member].name);
+}
+
+
+static int sighandler_lua_create(lua_State *L)
+{
+
+    mrp_context_t    *ctx    = mrp_lua_get_murphy_context();
+    char              e[128] = "";
+    sighandler_lua_t *h;
+    int               narg;
+
+    if (ctx == NULL)
+        luaL_error(L, "failed to get murphy context");
+
+    narg = lua_gettop(L);
+
+    h = (sighandler_lua_t *)mrp_lua_create_object(L, SIGHANDLER_LUA_CLASS,
+                                                  NULL, 0);
+    h->L        = L;
+    h->callback = LUA_NOREF;
+    h->data     = LUA_NOREF;
+
+    switch (narg) {
+    case 1:
+        break;
+    case 2:
+        if (mrp_lua_init_members(h, L, -2, e, sizeof(e)) != 1)
+            return luaL_error(L, "failed to initialize sighandler (%s)", e);
+        break;
+    default:
+        return luaL_error(L, "expecting 0 or 1 arguments, got %d", narg);
+    }
+
+    if (h->signum)
+        h->h = mrp_add_sighandler(ctx->ml, h->signum, sighandler_lua_cb, h);
+    else {
+        mrp_lua_destroy_object(L, NULL, 0, h);
+        return luaL_error(L, "signal number must be set in constructor");
+    }
+
+    if (h->h == NULL) {
+        mrp_lua_destroy_object(L, NULL, 0, h);
+        return luaL_error(L, "failed to create Murphy sighandler");
+    }
+
+    mrp_lua_push_object(L, h);
+
+    return 1;
+}
+
+
+static void sighandler_lua_destroy(void *data)
+{
+    sighandler_lua_t *h = (sighandler_lua_t *)data;
+
+    mrp_del_sighandler(h->h);
+    h->h = NULL;
+
+    mrp_lua_object_unref_value(h, h->L, h->callback);
+    mrp_lua_object_unref_value(h, h->L, h->data);
+    h->callback = LUA_NOREF;
+    h->data     = LUA_NOREF;
+}
+
+
+static sighandler_lua_t *sighandler_lua_check(lua_State *L, int idx)
+{
+    return (sighandler_lua_t *)mrp_lua_check_object(L,
+                                                    SIGHANDLER_LUA_CLASS, idx);
+}
+
+
+static int sighandler_lua_stringify(lua_State *L)
+{
+    sighandler_lua_t *h = sighandler_lua_check(L, 1);
+    const char       *s = strsignal(h->signum);
+
+    lua_pushfstring(L, "<%ssighandler %p(%p) of '%s'>",
+                    h->oneshot ? "oneshot " : "", h, h->h,
+                    s ? s : "unknown signal");
+
+    return 1;
+}
+
+
+MURPHY_REGISTER_LUA_BINDINGS(murphy, SIGHANDLER_LUA_CLASS,
+                             { "SigHandler", sighandler_lua_create });