mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Prevent await inside janet_call - address #1531
This was partially implemented before, but not in the case where the await or other signal itself was created by a C function. We have to separate code paths for generating signals - one via normal returns in janet_vm_continue, and the other via longjump. This adds handling for the longjump case, as well as improved messaging.
This commit is contained in:
		| @@ -62,6 +62,13 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) { | |||||||
|  |  | ||||||
| void janet_signalv(JanetSignal sig, Janet message) { | void janet_signalv(JanetSignal sig, Janet message) { | ||||||
|     if (janet_vm.return_reg != NULL) { |     if (janet_vm.return_reg != NULL) { | ||||||
|  |         /* Should match logic in janet_call for coercing everything not ok to an error (no awaits, yields, etc.) */ | ||||||
|  |         if (janet_vm.coerce_error && sig != JANET_SIGNAL_OK) { | ||||||
|  |             if (sig != JANET_SIGNAL_ERROR) { | ||||||
|  |                 message = janet_wrap_string(janet_formatc("%v coerced from %s to error", message, janet_signal_names[sig])); | ||||||
|  |             } | ||||||
|  |             sig = JANET_SIGNAL_ERROR; | ||||||
|  |         } | ||||||
|         *janet_vm.return_reg = message; |         *janet_vm.return_reg = message; | ||||||
|         if (NULL != janet_vm.fiber) { |         if (NULL != janet_vm.fiber) { | ||||||
|             janet_vm.fiber->flags |= JANET_FIBER_DID_LONGJUMP; |             janet_vm.fiber->flags |= JANET_FIBER_DID_LONGJUMP; | ||||||
|   | |||||||
| @@ -100,6 +100,7 @@ struct JanetVM { | |||||||
|      * return point for panics. */ |      * return point for panics. */ | ||||||
|     jmp_buf *signal_buf; |     jmp_buf *signal_buf; | ||||||
|     Janet *return_reg; |     Janet *return_reg; | ||||||
|  |     int coerce_error; | ||||||
|  |  | ||||||
|     /* The global registry for c functions. Used to store meta-data |     /* The global registry for c functions. Used to store meta-data | ||||||
|      * along with otherwise bare c function pointers. */ |      * along with otherwise bare c function pointers. */ | ||||||
|   | |||||||
| @@ -1373,7 +1373,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) { | |||||||
|  |  | ||||||
|     /* Run vm */ |     /* Run vm */ | ||||||
|     janet_vm.fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP; |     janet_vm.fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP; | ||||||
|  |     int old_coerce_error = janet_vm.coerce_error; | ||||||
|  |     janet_vm.coerce_error = 1; | ||||||
|     JanetSignal signal = run_vm(janet_vm.fiber, janet_wrap_nil()); |     JanetSignal signal = run_vm(janet_vm.fiber, janet_wrap_nil()); | ||||||
|  |     janet_vm.coerce_error = old_coerce_error; | ||||||
|  |  | ||||||
|     /* Teardown */ |     /* Teardown */ | ||||||
|     janet_vm.stackn = oldn; |     janet_vm.stackn = oldn; | ||||||
| @@ -1384,6 +1387,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (signal != JANET_SIGNAL_OK) { |     if (signal != JANET_SIGNAL_OK) { | ||||||
|  |         /* Should match logic in janet_signalv */ | ||||||
|  |         if (signal != JANET_SIGNAL_ERROR) { | ||||||
|  |             *janet_vm.return_reg = janet_wrap_string(janet_formatc("%v coerced from %s to error", *janet_vm.return_reg, janet_signal_names[signal])); | ||||||
|  |         } | ||||||
|         janet_panicv(*janet_vm.return_reg); |         janet_panicv(*janet_vm.return_reg); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1430,8 +1437,10 @@ void janet_try_init(JanetTryState *state) { | |||||||
|     state->vm_fiber = janet_vm.fiber; |     state->vm_fiber = janet_vm.fiber; | ||||||
|     state->vm_jmp_buf = janet_vm.signal_buf; |     state->vm_jmp_buf = janet_vm.signal_buf; | ||||||
|     state->vm_return_reg = janet_vm.return_reg; |     state->vm_return_reg = janet_vm.return_reg; | ||||||
|  |     state->coerce_error = janet_vm.coerce_error; | ||||||
|     janet_vm.return_reg = &(state->payload); |     janet_vm.return_reg = &(state->payload); | ||||||
|     janet_vm.signal_buf = &(state->buf); |     janet_vm.signal_buf = &(state->buf); | ||||||
|  |     janet_vm.coerce_error = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void janet_restore(JanetTryState *state) { | void janet_restore(JanetTryState *state) { | ||||||
| @@ -1440,6 +1449,7 @@ void janet_restore(JanetTryState *state) { | |||||||
|     janet_vm.fiber = state->vm_fiber; |     janet_vm.fiber = state->vm_fiber; | ||||||
|     janet_vm.signal_buf = state->vm_jmp_buf; |     janet_vm.signal_buf = state->vm_jmp_buf; | ||||||
|     janet_vm.return_reg = state->vm_return_reg; |     janet_vm.return_reg = state->vm_return_reg; | ||||||
|  |     janet_vm.coerce_error = state->coerce_error; | ||||||
| } | } | ||||||
|  |  | ||||||
| static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) { | static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) { | ||||||
|   | |||||||
| @@ -1261,6 +1261,7 @@ typedef struct { | |||||||
|     /* new state */ |     /* new state */ | ||||||
|     jmp_buf buf; |     jmp_buf buf; | ||||||
|     Janet payload; |     Janet payload; | ||||||
|  |     int coerce_error; | ||||||
| } JanetTryState; | } JanetTryState; | ||||||
|  |  | ||||||
| /***** END SECTION TYPES *****/ | /***** END SECTION TYPES *****/ | ||||||
|   | |||||||
| @@ -465,4 +465,13 @@ | |||||||
| # Close chat server | # Close chat server | ||||||
| (:close chat-server) | (:close chat-server) | ||||||
|  |  | ||||||
|  | # Issue #1531 | ||||||
|  | (def c (ev/chan 0)) | ||||||
|  | (ev/spawn (while (def x (ev/take c)))) | ||||||
|  | (defn print-to-chan [x] (ev/give c x)) | ||||||
|  | (assert-error "coerce await inside janet_call to error" | ||||||
|  |               (with-dyns [*out* print-to-chan] | ||||||
|  |                 (pp :foo))) | ||||||
|  | (ev/chan-close c) | ||||||
|  |  | ||||||
| (end-suite) | (end-suite) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose