From 273c36ef78cd5215c3dfd57977cde1188193b0ef Mon Sep 17 00:00:00 2001
From: Thierry Fournier <thierry.fournier@ozon.io>
Date: Mon, 21 May 2018 19:42:47 +0200
Subject: [PATCH 1/2] MINOR: lua: Improve error message

The function hlua_ctx_resume return less text message and more error
code. These error code allow the caller to return appropriate
message to the user.
---
 include/types/hlua.h |   3 ++
 src/hlua.c           | 131 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 24 deletions(-)

diff --git a/include/types/hlua.h b/include/types/hlua.h
index e8daf53..5a8173f 100644
--- a/include/types/hlua.h
+++ b/include/types/hlua.h
@@ -47,6 +47,9 @@ enum hlua_exec {
 	HLUA_E_OK = 0,
 	HLUA_E_AGAIN,  /* LUA yield, must resume the stack execution later, when
 	                  the associatedtask is waked. */
+	HLUA_E_ETMOUT, /* Execution timeout */
+	HLUA_E_NOMEM,  /* Out of memory error */
+	HLUA_E_YIELD,  /* LUA code try to yield, and this is not allowed */
 	HLUA_E_ERRMSG, /* LUA stack execution failed with a string error message
 	                  in the top of stack. */
 	HLUA_E_ERR,    /* LUA stack execution failed without error message. */
diff --git a/src/hlua.c b/src/hlua.c
index 370fc7e..727d664 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -1034,12 +1034,7 @@ resume_execution:
 		lua->run_time += now_ms - lua->start_time;
 		if (lua->max_time && lua->run_time > lua->max_time) {
 			lua_settop(lua->T, 0); /* Empty the stack. */
-			if (!lua_checkstack(lua->T, 1)) {
-				ret = HLUA_E_ERR;
-				break;
-			}
-			lua_pushfstring(lua->T, "execution timeout");
-			ret = HLUA_E_ERRMSG;
+			ret = HLUA_E_ETMOUT;
 			break;
 		}
 		/* Process the forced yield. if the general yield is not allowed or
@@ -1055,12 +1050,7 @@ resume_execution:
 		}
 		if (!yield_allowed) {
 			lua_settop(lua->T, 0); /* Empty the stack. */
-			if (!lua_checkstack(lua->T, 1)) {
-				ret = HLUA_E_ERR;
-				break;
-			}
-			lua_pushfstring(lua->T, "yield not allowed");
-			ret = HLUA_E_ERRMSG;
+			ret = HLUA_E_YIELD;
 			break;
 		}
 		ret = HLUA_E_AGAIN;
@@ -1096,12 +1086,7 @@ resume_execution:
 	case LUA_ERRMEM:
 		lua->wake_time = TICK_ETERNITY;
 		lua_settop(lua->T, 0); /* Empty the stack. */
-		if (!lua_checkstack(lua->T, 1)) {
-			ret = HLUA_E_ERR;
-			break;
-		}
-		lua_pushfstring(lua->T, "out of memory error");
-		ret = HLUA_E_ERRMSG;
+		ret = HLUA_E_NOMEM;
 		break;
 
 	case LUA_ERRERR:
@@ -1123,12 +1108,7 @@ resume_execution:
 	default:
 		lua->wake_time = TICK_ETERNITY;
 		lua_settop(lua->T, 0); /* Empty the stack. */
-		if (!lua_checkstack(lua->T, 1)) {
-			ret = HLUA_E_ERR;
-			break;
-		}
-		lua_pushfstring(lua->T, "unknonwn error");
-		ret = HLUA_E_ERRMSG;
+		ret = HLUA_E_ERR;
 		break;
 	}
 
@@ -1147,6 +1127,9 @@ resume_execution:
 		HLUA_CLR_RUN(lua);
 		break;
 
+	case HLUA_E_ETMOUT:
+	case HLUA_E_NOMEM:
+	case HLUA_E_YIELD:
 	case HLUA_E_ERR:
 		HLUA_CLR_RUN(lua);
 		notification_purge(&lua->com);
@@ -5756,6 +5739,18 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp,
 		lua_pop(stream->hlua->T, 1);
 		return 0;
 
+	case HLUA_E_ETMOUT:
+		SEND_ERR(stream->be, "Lua converter '%s': execution timeout.\n", fcn->name);
+		return 0;
+
+	case HLUA_E_NOMEM:
+		SEND_ERR(stream->be, "Lua converter '%s': out of memory error.\n", fcn->name);
+		return 0;
+
+	case HLUA_E_YIELD:
+		SEND_ERR(stream->be, "Lua converter '%s': yield functions like core.tcp() or core.sleep() are not allowed.\n", fcn->name);
+		return 0;
+
 	case HLUA_E_ERR:
 		/* Display log. */
 		SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
@@ -5888,6 +5883,24 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp
 		lua_pop(stream->hlua->T, 1);
 		return 0;
 
+	case HLUA_E_ETMOUT:
+		if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
+			stream_int_retnclose(&stream->si[0], &msg);
+		SEND_ERR(smp->px, "Lua sample-fetch '%s': execution timeout.\n", fcn->name);
+		return 0;
+
+	case HLUA_E_NOMEM:
+		if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
+			stream_int_retnclose(&stream->si[0], &msg);
+		SEND_ERR(smp->px, "Lua sample-fetch '%s': out of memory error.\n", fcn->name);
+		return 0;
+
+	case HLUA_E_YIELD:
+		if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
+			stream_int_retnclose(&stream->si[0], &msg);
+		SEND_ERR(smp->px, "Lua sample-fetch '%s': yield not allowed.\n", fcn->name);
+		return 0;
+
 	case HLUA_E_ERR:
 		if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
 			stream_int_retnclose(&stream->si[0], &msg);
@@ -6162,6 +6175,31 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
 		lua_pop(s->hlua->T, 1);
 		return ACT_RET_CONT;
 
+	case HLUA_E_ETMOUT:
+		if (!consistency_check(s, dir, &s->hlua->cons)) {
+			stream_int_retnclose(&s->si[0], &msg);
+			return ACT_RET_ERR;
+		}
+		SEND_ERR(px, "Lua function '%s': execution timeout.\n", rule->arg.hlua_rule->fcn.name);
+		return 0;
+
+	case HLUA_E_NOMEM:
+		if (!consistency_check(s, dir, &s->hlua->cons)) {
+			stream_int_retnclose(&s->si[0], &msg);
+			return ACT_RET_ERR;
+		}
+		SEND_ERR(px, "Lua function '%s': out of memory error.\n", rule->arg.hlua_rule->fcn.name);
+		return 0;
+
+	case HLUA_E_YIELD:
+		if (!consistency_check(s, dir, &s->hlua->cons)) {
+			stream_int_retnclose(&s->si[0], &msg);
+			return ACT_RET_ERR;
+		}
+		SEND_ERR(px, "Lua function '%s': aborting Lua processing on expired timeout.\n",
+		         rule->arg.hlua_rule->fcn.name);
+		return 0;
+
 	case HLUA_E_ERR:
 		if (!consistency_check(s, dir, &s->hlua->cons)) {
 			stream_int_retnclose(&s->si[0], &msg);
@@ -6336,6 +6374,21 @@ static void hlua_applet_tcp_fct(struct appctx *ctx)
 		lua_pop(hlua->T, 1);
 		goto error;
 
+	case HLUA_E_ETMOUT:
+		SEND_ERR(px, "Lua applet tcp '%s': execution timeout.\n",
+		         rule->arg.hlua_rule->fcn.name);
+		goto error;
+
+	case HLUA_E_NOMEM:
+		SEND_ERR(px, "Lua applet tcp '%s': out of memory error.\n",
+		         rule->arg.hlua_rule->fcn.name);
+		goto error;
+
+	case HLUA_E_YIELD: /* unexpected */
+		SEND_ERR(px, "Lua applet tcp '%s': yield not allowed.\n",
+		         rule->arg.hlua_rule->fcn.name);
+		goto error;
+
 	case HLUA_E_ERR:
 		/* Display log. */
 		SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
@@ -6575,6 +6628,21 @@ static void hlua_applet_http_fct(struct appctx *ctx)
 			lua_pop(hlua->T, 1);
 			goto error;
 
+		case HLUA_E_ETMOUT:
+			SEND_ERR(px, "Lua applet http '%s': execution timeout.\n",
+			         rule->arg.hlua_rule->fcn.name);
+			goto error;
+
+		case HLUA_E_NOMEM:
+			SEND_ERR(px, "Lua applet http '%s': out of memory error.\n",
+			         rule->arg.hlua_rule->fcn.name);
+			goto error;
+
+		case HLUA_E_YIELD: /* unexpected */
+			SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n",
+			         rule->arg.hlua_rule->fcn.name);
+			goto error;
+
 		case HLUA_E_ERR:
 			/* Display log. */
 			SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
@@ -7068,6 +7136,21 @@ static int hlua_cli_io_handler_fct(struct appctx *appctx)
 		lua_pop(hlua->T, 1);
 		return 1;
 
+	case HLUA_E_ETMOUT:
+		SEND_ERR(NULL, "Lua converter '%s': execution timeout.\n",
+		         fcn->name);
+		return 1;
+
+	case HLUA_E_NOMEM:
+		SEND_ERR(NULL, "Lua converter '%s': out of memory error.\n",
+		         fcn->name);
+		return 1;
+
+	case HLUA_E_YIELD: /* unexpected */
+		SEND_ERR(NULL, "Lua converter '%s': yield not allowed.\n",
+		         fcn->name);
+		return 1;
+
 	case HLUA_E_ERR:
 		/* Display log. */
 		SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
-- 
2.10.1

