Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
EMILUA(7)			Emilua reference		       EMILUA(7)

NAME
     Emilua - Lua execution engine

DESCRIPTION
     If  you want to embed Emilua in your own Boost.Asio-based programs, this is
     the list of steps you need to do:

      1. Compile and link against Emilua (use Meson or pkg-config  to  have  the
	 appropriate compiler flags filled automatically).

      2. #include <emilua/state.hpp>

      3. Instantiate emilua::app_context. This object needs to stay alive for as
	 long as at least one Lua VM is alive. If you want to be sure, just make
	 sure it outlives boost::asio::io_context and you're good to go.

       4. Make	sure all asio::io_context objects store an option (asio::config)
	 for scheduler/concurrency_hint. Alternatively you may use emilua::prop-
	 erties_service on older ASIO versions.

      5. Call emilua::make_vm() (see src/main.ypp for an example).

      6. Call emilua::vm_context::fiber_resume() inside the strand  returned  by
	 emilua::vm_context::strand()  to start the Lua VM created in the previ-
	 ous step (see src/main.ypp for an example).

      7. Optionally synchronize against other threads before you exit the appli-
	 cation. If you're going to spawn actors in foreign boost::asio::io_con-
	 text objects in your Lua programs then it's a good idea to include this
	 step. See below.

	 Warning

	 Emilua is not	designed  to  work  properly  with  boost::asio::io_con-
	 text::stop().	Many cleanup steps will be missed if you call this func-
	 tion. If you need to use it, then spawn Emilua programs  in  their  own
	 boost::asio::io_context instances.

emilua::app_context
     This  type  stores process-wide info that is shared among all Lua VMs (e.g.
     process arguments, environment, module paths, module caches,  default  log-
     ger, which VM is the master VM, ...).

     If  you  want  to	embed  the  Lua  programs in your binary as well you can
     pre-populate the module cache here with the contents of all Lua  files  you
     intend  to  ship in the binary. modules_cache_registry is the member you're
     looking for. Do this before you start the first Lua VM. However  there's  a
     better way (see next section).

BUILTIN MODULES
     Just  define  some or all of the following 3 functions and your module name
     resolution will be favoured over filesystem queries:

     *	 emilua::get_builtin_module

     *	 emilua::get_builtin_rdf_ec

     *	 emilua::get_builtin_native_module

     Using this method instead of pre-filling the  module  cache  allows  actors
     spawned  in  subprocesses	to import these modules as well. This method may
     also lead to better start-up times and  a	smaller  memory  footprint  (you
     could even use gperf to have the best module search performance).

MASTER VM
     If  you  want  to	allow  your Lua programs to change process state that is
     shared among all program threads (e.g. current  working  directory,  signal
     handlers, ...) then you need to elect one Lua VM to be the master VM.

     The  1-one  snippet  that follows is enough to finish this setup. This step
     must be done before you call fiber_resume().

	 appctx.master_vm = vm_ctx;

CLEANUP AT EXIT
     First make sure emilua::app_context outlives boost::asio::io_context.

     After boost::asio::io_context::run() returns  you	can  use  the  following
     snippet  to  synchronize  against extra threads and boost::asio::io_context
     objects your Lua scripts created[1].

	 {
	     std::unique_lock<std::mutex> lk{appctx.extra_threads_count_mtx};
	     while (appctx.extra_threads_count > 0)
		 appctx.extra_threads_count_empty_cond.wait(lk);
	 }

ACTORS SPAWNED IN DIFFERENT PROCESSES
     Emilua has the ability to spawn Lua VMs in their own processes  for  isola-
     tion  or  sandboxing purposes. To enable this feature, a supervisor process
     must be created while the program is still single-threaded.

     For communication with the supervisor process, Emilua uses an UNIX  socket.
     The  file	descriptor  for  this  process is stored in app_context::ipc_ac-
     tor_service_sockfd. See src/main.ypp for an example on  how  to  initialize
     this variable.

     On Linux, you also need to initialize emilua::clone_stack_address.

     If  you  don't intend to have Lua VMs tied to their own processes triggered
     by Lua programs then you can skip this step.

INHERITED LOW-NUMBERED FILE DESCRIPTORS
     After file descriptors are allocated in the process table by some	library,
     it's already too late detect whether some arbitrary file descriptor was in-
     herited  from  the parent process. If you're planning to allow Lua-programs
     to take control over these file descriptors (i.e. system.get_lowfd()),  you
     must  add some logic at the program startup (before any new file descriptor
     is allocated) to check which file descriptors were inherited  and	are  al-
     lowed to be manipulated from Lua programs and store them in the Emilua reg-
     istry:

	 std::array<bool, 7> lowfds;
	 lowfds.fill(false);

	 for (int fd = 3 ; fd <= 9 ; ++fd) {
	     if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) {
		 lowfds[fd - 3] = true;
	     }
	 }

	 // ...

	 emilua::app_context appctx;
	 appctx.lowfds = lowfds;

RT SIGNALS
     Emilua  reserves  a  RT  signal for internal uses (cancelling IO operations
     which have poor system APIs). This signal can be configured at build time:

	 meson configure -Deintr_rtsigno=RTSIGNO

     If you choose the value 0, this support is disabled altogether  and  Emilua
     won't reserve any RT signal by itself. If this support is enabled, you must
     add some code similar to the following one in main():

	 struct sigaction sa;
	 std::memset(&sa, 0, sizeof(struct sigaction));

	 sigemptyset(&sa.sa_mask);
	 sigaddset(&sa.sa_mask, EMILUA_CONFIG_EINTR_RTSIGNO);
	 sigprocmask(SIG_BLOCK, &sa.sa_mask, /*oldset=*/NULL);

	 sa.sa_sigaction = emilua::longjmp_on_rtsigno;
	 sa.sa_flags = SA_RESTART | SA_SIGINFO;
	 sigaction(EMILUA_CONFIG_EINTR_RTSIGNO, /*act=*/&sa, /*oldact=*/NULL);

LIBEMILUA-MAIN
     If aren't trying to embed Emilua into an existing application and just want
     to  create  a  single-binary application embedding the Lua sources it'll be
     easier to just use libemilua-main. It's a ready to roll implementation  for
     the  function main() with some hooks you may use to customize simple behav-
     ior.

NOTES
     [1]    Emilua only instantiates new threads and boost::asio::io_context ob-
	    jects if your Lua programs explicitly ask for  that  when  it  calls
	    spawn_vm().  You  can  also disable this feature altogether at build
	    time.

Emilua 0.12.1			   2025-11-24			       EMILUA(7)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=emilua-embedding&sektion=7&manpath=FreeBSD+Ports+15.1.quarterly>

home | help