MINOR: hlua: support for optional arguments to core.register_task()

core.register_task(function) may now take up to 4 additional arguments
that will be passed as-is to the task function.
This could be convenient to spawn sub-tasks from existing functions
supporting core.register_task() without the need to use global
variables to pass some context to the newly created task function.

The new prototype is:

  core.register_task(function[, arg1[, arg2[, ...[, arg4]]]])

Implementation remains backward-compatible with existing scripts.
diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
index 146c050..917b684 100644
--- a/doc/lua-api/index.rst
+++ b/doc/lua-api/index.rst
@@ -720,7 +720,7 @@
 
   It takes no input, and no output is expected.
 
-.. js:function:: core.register_task(func)
+.. js:function:: core.register_task(func[, arg1[, arg2[, ...[, arg4]]]])
 
   **context**: body, init, task, action, sample-fetch, converter
 
@@ -728,16 +728,19 @@
   main scheduler starts. For example this type of tasks can be executed to
   perform complex health checks.
 
-  :param function func: is the Lua function called to work as initializer.
+  :param function func: is the Lua function called to work as an async task.
+
+  Up to 4 optional arguments (all types supported) may be passed to the function.
+  (They will be passed as-is to the task function)
 
   The prototype of the Lua function used as argument is:
 
 .. code-block:: lua
 
-    function()
+    function([arg1[, arg2[, ...[, arg4]]]])
 ..
 
-  It takes no input, and no output is expected.
+  It takes up to 4 optional arguments (provided when registering), and no output is expected.
 
 .. js:function:: core.register_cli([path], usage, func)
 
diff --git a/src/hlua.c b/src/hlua.c
index 19f848a..7e0a1ca 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -8686,19 +8686,38 @@
  *
  * Lua prototype:
  *
- *   <none> core.register_task(<function>)
+ *   <none> core.register_task(<function>[, <arg1>[, <arg2>[, ...[, <arg4>]]]])
+ *
+ * <arg1..4> are optional arguments that will be provided to <function>
  */
 static int hlua_register_task(lua_State *L)
 {
 	struct hlua *hlua = NULL;
 	struct task *task = NULL;
 	int ref;
+	int nb_arg;
+	int it;
+	int arg_ref[4]; /* optional arguments */
 	int state_id;
 
-	MAY_LJMP(check_args(L, 1, "register_task"));
+	nb_arg = lua_gettop(L);
+	if (nb_arg < 1)
+		WILL_LJMP(luaL_error(L, "register_task: <func> argument is required"));
+	else if (nb_arg > 5)
+		WILL_LJMP(luaL_error(L, "register_task: no more that 4 optional arguments may be provided"));
 
+	/* first arg: function ref */
 	ref = MAY_LJMP(hlua_checkfunction(L, 1));
 
+	/* extract optional args (if any) */
+	it = 0;
+	while (--nb_arg) {
+		lua_pushvalue(L, 2 + it);
+		arg_ref[it] = hlua_ref(L); /* get arg reference */
+		it += 1;
+	}
+	nb_arg = it;
+
 	/* Get the reference state. If the reference is NULL, L is the master
 	 * state, otherwise hlua->T is.
 	 */
@@ -8731,12 +8750,26 @@
 	if (!hlua_ctx_init(hlua, state_id, task))
 		goto alloc_error;
 
+	/* Ensure there is enough space on the stack for the function
+	 * plus optional arguments
+	 */
+	if (!lua_checkstack(hlua->T, (1 + nb_arg)))
+		goto alloc_error;
+
 	/* Restore the function in the stack. */
 	hlua_pushref(hlua->T, ref);
 	/* function ref not needed anymore since it was pushed to the substack */
 	hlua_unref(L, ref);
 
-	hlua->nargs = 0;
+	hlua->nargs = nb_arg;
+
+	/* push optional arguments to the function */
+	for (it = 0; it < nb_arg; it++) {
+		/* push arg to the stack */
+		hlua_pushref(hlua->T, arg_ref[it]);
+		/* arg ref not needed anymore since it was pushed to the substack */
+		hlua_unref(L, arg_ref[it]);
+	}
 
 	/* Schedule task. */
 	task_wakeup(task, TASK_WOKEN_INIT);
@@ -8746,6 +8779,9 @@
   alloc_error:
 	task_destroy(task);
 	hlua_unref(L, ref);
+	for (it = 0; it < nb_arg; it++) {
+		hlua_unref(L, arg_ref[it]);
+	}
 	hlua_ctx_destroy(hlua);
 	WILL_LJMP(luaL_error(L, "Lua out of memory error."));
 	return 0; /* Never reached */