aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani2020-03-26 17:22:25 +0100
committerPhilipp Stephani2020-03-26 21:47:25 +0100
commitd28b00476890f791a89b65007e5f20682b3eaa0d (patch)
tree3bb04c984ed5b74e661291b71579fe8d04070f69 /src
parent934b3c9ecc2b91723b9e5826080424ec1a90f264 (diff)
downloademacs-d28b00476890f791a89b65007e5f20682b3eaa0d.tar.gz
emacs-d28b00476890f791a89b65007e5f20682b3eaa0d.zip
Add a module function to open a file descriptor connected to a pipe.
A common complaint about the module API is that modules can't communicate asynchronously with Emacs. While it isn't possible to call arbitrary Emacs functions asynchronously, writing to a pipe should always be fine and is a pretty low-hanging fruit. This patch implements a function that adapts an existing pipe process. That way, users can use familiar tools like process filters or 'accept-process-output'. * src/module-env-28.h: Add 'open_channel' module function. * src/emacs-module.c (module_open_channel): Provide definition for 'open_channel'. (initialize_environment): Use it. * src/process.c (open_channel_for_module): New helper function. (syms_of_process): Define necessary symbol. * test/src/emacs-module-tests.el (module/async-pipe): New unit test. * test/data/emacs-module/mod-test.c (signal_system_error): New helper function. (signal_errno): Use it. (write_to_pipe): New function running in the background. (Fmod_test_async_pipe): New test module function. (emacs_module_init): Export it. * doc/lispref/internals.texi (Module Misc): Document new module function. * doc/lispref/processes.texi (Asynchronous Processes): New anchor for pipe processes. * etc/NEWS: Document 'open_channel' function.
Diffstat (limited to 'src')
-rw-r--r--src/emacs-module.c9
-rw-r--r--src/module-env-28.h3
-rw-r--r--src/process.c12
-rw-r--r--src/process.h2
4 files changed, 26 insertions, 0 deletions
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 60f16418efa..cdcbe061b53 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -88,6 +88,7 @@ To add a new module function, proceed as follows:
88#include "dynlib.h" 88#include "dynlib.h"
89#include "coding.h" 89#include "coding.h"
90#include "keyboard.h" 90#include "keyboard.h"
91#include "process.h"
91#include "syssignal.h" 92#include "syssignal.h"
92#include "sysstdio.h" 93#include "sysstdio.h"
93#include "thread.h" 94#include "thread.h"
@@ -977,6 +978,13 @@ module_make_big_integer (emacs_env *env, int sign,
977 return lisp_to_value (env, make_integer_mpz ()); 978 return lisp_to_value (env, make_integer_mpz ());
978} 979}
979 980
981static int
982module_open_channel (emacs_env *env, emacs_value pipe_process)
983{
984 MODULE_FUNCTION_BEGIN (-1);
985 return open_channel_for_module (value_to_lisp (pipe_process));
986}
987
980 988
981/* Subroutines. */ 989/* Subroutines. */
982 990
@@ -1391,6 +1399,7 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv)
1391 env->make_big_integer = module_make_big_integer; 1399 env->make_big_integer = module_make_big_integer;
1392 env->get_function_finalizer = module_get_function_finalizer; 1400 env->get_function_finalizer = module_get_function_finalizer;
1393 env->set_function_finalizer = module_set_function_finalizer; 1401 env->set_function_finalizer = module_set_function_finalizer;
1402 env->open_channel = module_open_channel;
1394 Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments); 1403 Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments);
1395 return env; 1404 return env;
1396} 1405}
diff --git a/src/module-env-28.h b/src/module-env-28.h
index a2479a8f744..5d884c148c4 100644
--- a/src/module-env-28.h
+++ b/src/module-env-28.h
@@ -9,3 +9,6 @@
9 void (*set_function_finalizer) (emacs_env *env, emacs_value arg, 9 void (*set_function_finalizer) (emacs_env *env, emacs_value arg,
10 void (*fin) (void *) EMACS_NOEXCEPT) 10 void (*fin) (void *) EMACS_NOEXCEPT)
11 EMACS_ATTRIBUTE_NONNULL (1); 11 EMACS_ATTRIBUTE_NONNULL (1);
12
13 int (*open_channel) (emacs_env *env, emacs_value pipe_process)
14 EMACS_ATTRIBUTE_NONNULL (1);
diff --git a/src/process.c b/src/process.c
index e4e5e57aeee..07881d6c5d3 100644
--- a/src/process.c
+++ b/src/process.c
@@ -8200,6 +8200,17 @@ restore_nofile_limit (void)
8200#endif 8200#endif
8201} 8201}
8202 8202
8203int
8204open_channel_for_module (Lisp_Object process)
8205{
8206 CHECK_PROCESS (process);
8207 CHECK_TYPE (PIPECONN_P (process), Qpipe_process_p, process);
8208 int fd = dup (XPROCESS (process)->open_fd[SUBPROCESS_STDOUT]);
8209 if (fd == -1)
8210 report_file_error ("Cannot duplicate file descriptor", Qnil);
8211 return fd;
8212}
8213
8203 8214
8204/* This is not called "init_process" because that is the name of a 8215/* This is not called "init_process" because that is the name of a
8205 Mach system call, so it would cause problems on Darwin systems. */ 8216 Mach system call, so it would cause problems on Darwin systems. */
@@ -8446,6 +8457,7 @@ amounts of data in one go. */);
8446 DEFSYM (Qinterrupt_process_functions, "interrupt-process-functions"); 8457 DEFSYM (Qinterrupt_process_functions, "interrupt-process-functions");
8447 8458
8448 DEFSYM (Qnull, "null"); 8459 DEFSYM (Qnull, "null");
8460 DEFSYM (Qpipe_process_p, "pipe-process-p");
8449 8461
8450 defsubr (&Sprocessp); 8462 defsubr (&Sprocessp);
8451 defsubr (&Sget_process); 8463 defsubr (&Sget_process);
diff --git a/src/process.h b/src/process.h
index 7884efc5494..a783a31cb86 100644
--- a/src/process.h
+++ b/src/process.h
@@ -300,6 +300,8 @@ extern Lisp_Object remove_slash_colon (Lisp_Object);
300extern void update_processes_for_thread_death (Lisp_Object); 300extern void update_processes_for_thread_death (Lisp_Object);
301extern void dissociate_controlling_tty (void); 301extern void dissociate_controlling_tty (void);
302 302
303extern int open_channel_for_module (Lisp_Object);
304
303INLINE_HEADER_END 305INLINE_HEADER_END
304 306
305#endif /* EMACS_PROCESS_H */ 307#endif /* EMACS_PROCESS_H */