aboutsummaryrefslogtreecommitdiffstats
path: root/test/data
diff options
context:
space:
mode:
authorPhilipp Stephani2019-01-02 22:04:56 +0100
committerPhilipp Stephani2019-02-24 22:43:07 +0100
commit72ec233f2a1b8a6a9574e61588d0467caf41755c (patch)
tree725add4413feb9cb7789576294099096e63d3044 /test/data
parent5653b76d0bacf1edfc3d962c0bb991344cd80f6f (diff)
downloademacs-72ec233f2a1b8a6a9574e61588d0467caf41755c.tar.gz
emacs-72ec233f2a1b8a6a9574e61588d0467caf41755c.zip
Ignore pending_signals when checking for quits.
pending_signals is often set if no quit is pending. This results in bugs in module code if the module returns but no quit is actually pending. As a better alternative, add a new process_input environment function for Emacs 27. That function processes signals (like maybe_quit). * configure.ac: Add module snippet for Emacs 27. * src/module-env-27.h: New file. * src/emacs-module.h.in: Add process_input function to environment interface. * src/emacs-module.c (module_should_quit): Use QUITP macro to check whether the caller should quit. (module_process_input): New function. (initialize_environment): Use it. * src/eval.c: Remove obsolete comment. * test/data/emacs-module/mod-test.c (signal_wrong_type_argument) (signal_errno): New helper functions. (Fmod_test_sleep_until): New test module function. * test/src/emacs-module-tests.el (mod-test-sleep-until): New unit test. * doc/lispref/internals.texi (Module Misc): Document process_input.
Diffstat (limited to 'test/data')
-rw-r--r--test/data/emacs-module/mod-test.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/test/data/emacs-module/mod-test.c b/test/data/emacs-module/mod-test.c
index 98242e85baf..47ea159d0e7 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -17,12 +17,20 @@ GNU General Public License for more details.
17You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20#include "config.h"
21
20#include <assert.h> 22#include <assert.h>
23#include <errno.h>
24#include <limits.h>
21#include <stdio.h> 25#include <stdio.h>
22#include <stdlib.h> 26#include <stdlib.h>
23#include <limits.h> 27#include <string.h>
28#include <time.h>
29
24#include <emacs-module.h> 30#include <emacs-module.h>
25 31
32#include "timespec.h"
33
26int plugin_is_GPL_compatible; 34int plugin_is_GPL_compatible;
27 35
28#if INTPTR_MAX <= 0 36#if INTPTR_MAX <= 0
@@ -299,6 +307,64 @@ Fmod_test_invalid_finalizer (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
299 return env->funcall (env, env->intern (env, "garbage-collect"), 0, NULL); 307 return env->funcall (env, env->intern (env, "garbage-collect"), 0, NULL);
300} 308}
301 309
310static void
311signal_wrong_type_argument (emacs_env *env, const char *predicate,
312 emacs_value arg)
313{
314 emacs_value symbol = env->intern (env, "wrong-type-argument");
315 emacs_value elements[2] = {env->intern (env, predicate), arg};
316 emacs_value data = env->funcall (env, env->intern (env, "list"), 2, elements);
317 env->non_local_exit_signal (env, symbol, data);
318}
319
320static void
321signal_errno (emacs_env *env, const char *function)
322{
323 const char *message = strerror (errno);
324 emacs_value message_value = env->make_string (env, message, strlen (message));
325 emacs_value symbol = env->intern (env, "file-error");
326 emacs_value elements[2]
327 = {env->make_string (env, function, strlen (function)), message_value};
328 emacs_value data = env->funcall (env, env->intern (env, "list"), 2, elements);
329 env->non_local_exit_signal (env, symbol, data);
330}
331
332/* A long-running operation that occasionally calls `should_quit' or
333 `process_input'. */
334
335static emacs_value
336Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
337 void *data)
338{
339 assert (nargs == 2);
340 const double until_seconds = env->extract_float (env, args[0]);
341 if (env->non_local_exit_check (env))
342 return NULL;
343 if (until_seconds <= 0)
344 {
345 signal_wrong_type_argument (env, "cl-plusp", args[0]);
346 return NULL;
347 }
348 const bool process_input = env->is_not_nil (env, args[1]);
349 const struct timespec until = dtotimespec (until_seconds);
350 const struct timespec amount = make_timespec(0, 10000000);
351 while (true)
352 {
353 const struct timespec now = current_timespec ();
354 if (timespec_cmp (now, until) >= 0)
355 break;
356 if (nanosleep (&amount, NULL) && errno != EINTR)
357 {
358 signal_errno (env, "nanosleep");
359 return NULL;
360 }
361 if ((process_input
362 && env->process_input (env) == emacs_process_input_quit)
363 || env->should_quit (env))
364 return NULL;
365 }
366 return env->intern (env, "finished");
367}
302 368
303/* Lisp utilities for easier readability (simple wrappers). */ 369/* Lisp utilities for easier readability (simple wrappers). */
304 370
@@ -367,6 +433,7 @@ emacs_module_init (struct emacs_runtime *ert)
367 DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL); 433 DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
368 DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0, 434 DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
369 NULL, NULL); 435 NULL, NULL);
436 DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
370 437
371#undef DEFUN 438#undef DEFUN
372 439