@@ -39,29 +39,29 @@ void initialize_libuv_signal() {
3939}
4040
4141static bool signal_promise_is_finished (lean_uv_signal_object * signal) {
42- return lean_io_get_task_state_core ((lean_object *)lean_to_promise (signal->m_promise )->m_result ) == 2 ;
42+ return signal-> m_promise == NULL || lean_io_get_task_state_core ((lean_object *)lean_to_promise (signal->m_promise )->m_result ) == 2 ;
4343}
4444
4545void handle_signal_event (uv_signal_t * handle, int signum) {
4646 lean_object * obj = (lean_object*)handle->data ;
4747 lean_uv_signal_object * signal = lean_to_uv_signal (obj);
4848
4949 lean_assert (signal->m_state == SIGNAL_STATE_RUNNING);
50- lean_assert (signal->m_promise != NULL );
5150
5251 if (signal->m_repeating ) {
5352 if (!signal_promise_is_finished (signal)) {
5453 lean_object* res = lean_io_promise_resolve (lean_box (signum), signal->m_promise , lean_io_mk_world ());
5554 lean_dec (res);
5655 }
5756 } else {
58- lean_assert (!signal_promise_is_finished (signal));
57+ if (signal->m_promise != NULL ) {
58+ lean_object* res = lean_io_promise_resolve (lean_box (signum), signal->m_promise , lean_io_mk_world ());
59+ lean_dec (res);
60+ }
61+
5962 uv_signal_stop (signal->m_uv_signal );
6063 signal->m_state = SIGNAL_STATE_FINISHED;
6164
62- lean_object* res = lean_io_promise_resolve (lean_box (signum), signal->m_promise , lean_io_mk_world ());
63- lean_dec (res);
64-
6565 lean_dec (obj);
6666 }
6767}
@@ -154,33 +154,37 @@ extern "C" LEAN_EXPORT lean_obj_res lean_uv_signal_next(b_obj_arg obj, obj_arg /
154154 }
155155 case SIGNAL_STATE_RUNNING:
156156 {
157- lean_assert (signal->m_promise != NULL );
158- // 2 indicates finished
159157 if (signal_promise_is_finished (signal)) {
160- lean_dec (signal->m_promise );
158+ if (signal->m_promise != NULL ) {
159+ lean_dec (signal->m_promise );
160+ }
161+
161162 signal->m_promise = create_promise ();
162- lean_inc (signal->m_promise );
163- return lean_io_result_mk_ok (signal->m_promise );
164- } else {
165- lean_inc (signal->m_promise );
166- return lean_io_result_mk_ok (signal->m_promise );
167163 }
164+
165+ lean_inc (signal->m_promise );
166+ return lean_io_result_mk_ok (signal->m_promise );
168167 }
169168 case SIGNAL_STATE_FINISHED:
170169 {
171- lean_assert (signal->m_promise != NULL );
170+ if (signal->m_promise == NULL ) {
171+ lean_object* finished_promise = create_promise ();
172+ return lean_io_result_mk_ok (finished_promise);
173+ }
174+
172175 lean_inc (signal->m_promise );
173176 return lean_io_result_mk_ok (signal->m_promise );
174177 }
175178 }
176179 } else {
177180 if (signal->m_state == SIGNAL_STATE_INITIAL) {
178181 return setup_signal ();
179- } else {
180- lean_assert (signal->m_promise != NULL );
181-
182+ } else if (signal->m_promise != NULL ) {
182183 lean_inc (signal->m_promise );
183184 return lean_io_result_mk_ok (signal->m_promise );
185+ } else {
186+ lean_object* finished_promise = create_promise ();
187+ return lean_io_result_mk_ok (finished_promise);
184188 }
185189 }
186190}
@@ -190,12 +194,15 @@ extern "C" LEAN_EXPORT lean_obj_res lean_uv_signal_stop(b_obj_arg obj, obj_arg /
190194 lean_uv_signal_object * signal = lean_to_uv_signal (obj);
191195
192196 if (signal->m_state == SIGNAL_STATE_RUNNING) {
193- lean_assert (signal->m_promise != NULL );
194-
195197 event_loop_lock (&global_ev);
196198 int result = uv_signal_stop (signal->m_uv_signal );
197199 event_loop_unlock (&global_ev);
198200
201+ if (signal->m_promise != NULL ) {
202+ lean_dec (signal->m_promise );
203+ signal->m_promise = NULL ;
204+ }
205+
199206 signal->m_state = SIGNAL_STATE_FINISHED;
200207
201208 // The loop does not need to keep the signal alive anymore.
@@ -211,6 +218,30 @@ extern "C" LEAN_EXPORT lean_obj_res lean_uv_signal_stop(b_obj_arg obj, obj_arg /
211218 }
212219}
213220
221+ /* Std.Internal.UV.Signal.cancel (signal : @& Signal) : IO Unit */
222+ extern " C" LEAN_EXPORT lean_obj_res lean_uv_signal_cancel (b_obj_arg obj, obj_arg /* w */ ) {
223+ lean_uv_signal_object * signal = lean_to_uv_signal (obj);
224+
225+ // It's locking here to avoid changing the state during other operations.
226+ event_loop_lock (&global_ev);
227+
228+ if (signal->m_state == SIGNAL_STATE_RUNNING && signal->m_promise != NULL ) {
229+ if (signal->m_repeating ) {
230+ lean_dec (signal->m_promise );
231+ signal->m_promise = NULL ;
232+ } else {
233+ uv_signal_stop (signal->m_uv_signal );
234+ lean_dec (signal->m_promise );
235+ signal->m_promise = NULL ;
236+ signal->m_state = SIGNAL_STATE_INITIAL;
237+
238+ lean_dec (obj);
239+ }
240+ }
241+
242+ event_loop_unlock (&global_ev);
243+ return lean_io_result_mk_ok (lean_box (0 ));
244+ }
214245
215246#else
216247
@@ -235,6 +266,13 @@ extern "C" LEAN_EXPORT lean_obj_res lean_uv_signal_stop(b_obj_arg signal, obj_ar
235266 );
236267}
237268
269+ /* Std.Internal.UV.Signal.cancel (signal : @& Signal) : IO Unit */
270+ extern " C" LEAN_EXPORT lean_obj_res lean_uv_signal_cancel (b_obj_arg obj, obj_arg /* w */ ) {
271+ lean_always_assert (
272+ false && (" Please build a version of Lean4 with libuv to invoke this." )
273+ );
274+ }
275+
238276#endif
239277
240278}
0 commit comments