{"id":13578186,"url":"https://github.com/siffiejoe/lua-luaipc","last_synced_at":"2025-12-27T15:03:56.450Z","repository":{"id":147352803,"uuid":"53659672","full_name":"siffiejoe/lua-luaipc","owner":"siffiejoe","description":"Portable inter-process communication for Lua","archived":false,"fork":false,"pushed_at":"2019-07-04T06:44:58.000Z","size":82,"stargazers_count":47,"open_issues_count":4,"forks_count":9,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-05T15:49:27.435Z","etag":null,"topics":["inter-process-communication","lua","semaphore"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siffiejoe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-03-11T10:34:11.000Z","updated_at":"2024-05-17T21:22:10.000Z","dependencies_parsed_at":"2023-07-04T12:31:07.300Z","dependency_job_id":null,"html_url":"https://github.com/siffiejoe/lua-luaipc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-luaipc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-luaipc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-luaipc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-luaipc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siffiejoe","download_url":"https://codeload.github.com/siffiejoe/lua-luaipc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247366377,"owners_count":20927499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["inter-process-communication","lua","semaphore"],"created_at":"2024-08-01T15:01:28.248Z","updated_at":"2025-12-27T15:03:51.407Z","avatar_url":"https://github.com/siffiejoe.png","language":"C","readme":"[![Build Status](https://travis-ci.org/siffiejoe/lua-luaipc.svg?branch=master)](https://travis-ci.org/siffiejoe/lua-luaipc)\n\n#            LuaIPC -- Inter-Process Communication for Lua           #\n\n##                           Introduction                           ##\n\nSince Lua is mostly written in portable ISO C it comes with the bare\nminimum of batteries. There are some extension libraries that provide\na portable (usually lowest common denominator) interface to some parts\nof the operating system not covered by ISO C, like sockets\n([LuaSocket][1]), or filesystem operations ([LuaFileSystem][2]).\n**LuaIPC** is such a library consisting of multiple modules for\ninter-process communication in Lua. It allows you to:\n\n*   create/read/write shared memory\n*   create/manipulate semaphores\n*   memory-map files\n*   lock/unlock (parts of) files\n*   spawn subprocesses and communicate with them using unnamed pipes\n\nThe implementation should be portable to Lua 5.1-5.3 on recent Windows\nand POSIX machines (tested on Win 7, Ubuntu Linux, FreeBSD, and OSX).\n\n  [1]: http://w3.impa.br/~diego/software/luasocket/\n  [2]: http://keplerproject.github.io/luafilesystem/\n\n\n##                             Reference                            ##\n\nIn general all functions return a true-ish value on success (`true` if\nthere is nothing better to return). This applies only to functions\nthat do not aim for compatibility with existing Lua functions (like\ne.g.  the file methods). On error, usually `nil`, an error message,\nand a numeric error code are returned. All handles created by this\nlibrary are finalized during garbage-collection, so manually cleaning\nup is optional under most circumstances.\n\nThe **LuaIPC** library consists of the following modules:\n\n\n###                             ipc.shm                            ###\n\n```lua\nlocal shm = require( \"ipc.shm\" )\n```\n\nA shared memory segment is a piece of RAM that can be accessed by\nmultiple processes at the same time. Since Lua does not have any form\nof pointer arithmetic, a file-like interface is provided instead.\nThe shared memory segment is deleted automatically when all its\nhandles are closed. It is unspecified whether you can still open a\nnew handle to an existing shared memory segment once its original\ncreator has closed the handle. On some OSes this module might allocate\nmore than the requested number of bytes (usually a multiple of the\npage size). To be portable you have to agree on the real size (e.g.\nby storing it at the beginning of the shared memory segment) and\nadjust the file size that this module uses by calling `h:truncate()`\nfor all parties that attached to the shared memory (see below).\n\nThe module provides the following functions:\n\n*   `shm.create( name, size ) ==\u003e handle`\n*   `shm.attach( name ) ==\u003e handle`\n\n`shm.create()` creates a new shared memory segment with the given\n`name` and `size` (in bytes), and returns an attached handle to it. If\na memory segment with that `name` already exists, this function fails.\n`shm.attach()` on the other hand tries to open an existing shared\nmemory segment with the given `name`. In both cases `name` is not a\nfile path: you cannot find it on the filesystem (well, on POSIX you\ncan), and it must not contain any directory separators!\n\nA shared memory handle has all the methods that a normal Lua file\nhandle has, and additionally:\n\n*   `h:size() ==\u003e bytes`\n*   `h:addr() ==\u003e pointer`\n*   `h:truncate( bytes ) ==\u003e true`\n\n`h:size()` returns the size of the shared memory segment in bytes, and\n`h:addr()` returns the starting address as a lightuserdata. Unless you\nuse some form of FFI, this is probably not very useful for you. The\n`h:truncate()` method can tell this module to use less than the\ncurrent shared memory size for its file-like interface.\n\nThe file-like methods behave exactly like their Lua file equivalents\nwith the following exception: Currently the `\"*n\"` format specifier of\n`read`/`lines` is not supported. Since handles are not actually Lua\nfile objects, `io.type()` will return `nil` when called with such a\nhandle.\n\n\n###                             ipc.sem                            ###\n\n```lua\nlocal sem = require( \"ipc.sem\" )\n```\n\nA semaphore is a shared integer counter that you can atomically\nincrement or decrement, but its value will never go below zero. If a\ndecrement operation would cause the value to become negative, the call\nblocks (and/or returns `false` for the non-blocking/waiting calls).\nThe semaphore is deleted automatically when all its handles are\nclosed. It is unspecified whether you can still open a new handle to\nan existing semaphore once its original creator has closed the handle.\n\nThe module provides the following function:\n\n*   `sem.open( name [, n] ) ==\u003e handle`\n\nIf the initial counter value `n` is given (and not `0`), `sem.open`\ntries to create a new semaphore with the given `name`. If such a\nsemaphore already exists, this function fails. If `n` is zero or\nabsent, `sem.open` tries to open an existing semaphore with the given\n`name`. Anyways, `name` is not a file path: you cannot find it on the\nfilesystem (well, on POSIX you can), and it must not contain any\ndirectory separators!\n\nA semaphore handle has the following methods:\n\n*   `h:inc() ==\u003e true`\n*   `h:dec( [timeout] ) ==\u003e boolean`\n*   `h:close() ==\u003e true`\n\n`h:inc()` increments the semaphore value (if successful). `h:dec()`\ntries to decrement the semaphore value. If the optional `timeout` (in\nseconds, can have a fractional part) is absent or negative, the\nfunction will block until some other process increments the semaphore.\nOtherwise `h:dec()` will wait at most `timeout` seconds and return\n`true` or `false` depending on the success (errors still result in\n`nil`, error message, and error code).\n\n\n###                            ipc.mmap                            ###\n\n```lua\nlocal mmap = require( \"ipc.mmap\" )\n```\n\nMemory-mapped I/O is usually faster than normal file I/O, because by\nmaking the kernel buffers available at a certain memory address, you\ncan save the copy operations to user-supplied buffers. Memory-mapping\nalso has some draw-backs: Most OSes don't allow mapping a zero-length\nfile or very large files (e.g. larger than the address space). Also,\nthis module does not allow resizing the file while it is mapped, so\nyou can't write beyond the initial bounds of the memory-mapped file.\n\nThe module provides the following function:\n\n*   `mmap.pagesize`\n*   `mmap.open( filepath [, mode [, offset [, size]]] ) ==\u003e handle`\n\n`mmap.open()` opens the given `filepath` and maps the contents into\nmemory. `mode` can be `\"r\"` (the default), `\"w\"`, or `\"rw\"`. On\nsuccess a mmap handle is returned. Offsets usually must be given in\nmultiples of the current pages size (or equivalent). `mmap.pagesize`\ncontains this number. Default value for `size` is `0` which uses the\ncurrent size of the file.\n\nAn mmap handle has all the methods that a normal Lua file handle has,\nand additionally:\n\n*   `h:size() ==\u003e bytes`\n*   `h:addr() ==\u003e pointer`\n*   `h:truncate( bytes ) ==\u003e true`\n\n`h:size()` returns the size of the memory map in bytes, and `h:addr()`\nreturns the starting address as a lightuserdata. Unless you use some\nform of FFI, this is probably not very useful for you. `h:truncate()`\ncan shrink the size of the memory mapping, but it's mostly useful for\nthe `ipc.shm` module (see there).\n\nThe file-like methods behave exactly like their Lua file equivalents\nwith the following exception: Currently the `\"*n\"` format specifier of\n`read`/`lines` is not supported. Since handles are not actually Lua\nfile objects, `io.type()` will return `nil` when called with such a\nhandle.\n\n\n###                          ipc.filelock                          ###\n\n```lua\nlocal filelock = require( \"ipc.filelock\" )\n```\n\nThis module contains functions for (un-)locking byte ranges of an\nopened Lua file. The locks might be advisory (you have to check for\nlocks yourself) or mandatory (file functions will honor the locks\nautomatically) depending on the OS. Also, the file locking functions\ncan't be used to synchonize different threads in the same process.\nThere is similar functionality in [LuaFileSystem][2], but in LFS all\nlocking is non-blocking. It is explicitly *not* supported to mix the\nlocking functions from LFS and from this module.\n\nThis module provides the following functions:\n\n*   `filelock.lock( file, mode [, offset [, nbytes]] ) ==\u003e true`\n*   `filelock.trylock( file, mode [, offset [, nbytes]] ) ==\u003e boolean`\n*   `filelock.unlock( file [, offset [, nbytes]] ) ==\u003e true`\n\n`filelock.lock()` acquires a lock for the given range of `nbytes`\nbytes starting at `offset` (default `0`) in the Lua file object. If\n`nbytes` is absent (or `0`), the whole file is locked. If the given\nrange already is locked by another process, `filelock.lock()` will\nblock until the other process releases that lock. `filelock.trylock()`\nis similar, but it will not block. Instead it returns false if another\nprocess already holds a lock on the given byte range.\n`filelock.unlock` unlocks the given byte range that has been locked by\nthe same process before.\n\n\n###                            ipc.proc                            ###\n\n```lua\nlocal proc = require( \"ipc.proc\" )\n```\n\nOn the most common OSes Lua provides the `io.popen()` function to\nspawn a subprocess and capture its output *or* provide its input via\nunnamed pipes. This module can capture `stdout` *and* `stderr`\nsimultaneously, while still providing input for the spawned command.\nTo avoid deadlocks as much as possible and to work around platform\ndifferences the interface is callback-based.\n\nThis module provides the following functions/fields:\n\n*   `proc.spawn( cmd, options ) ==\u003e handle`\n*   `proc.EOF ==\u003e lightuserdata`\n\nSimilar to `os.execute()` and `io.popen()`, `proc.spawn()` takes a\ncommand (`cmd`) as string and runs it using the shell. The `options`\ntable specifies the callback function (field `callback`), and which\nstreams to redirect via pipes (fields `stdin`, `stdout`, and `stderr`;\na true value creates a pipe, a false value uses the default streams of\nthe parent process -- you can also specify Lua file objects).\n\nA process handle has the following methods:\n\n*   `h:write( ... ) ==\u003e true`\n*   `h:kill( \"term\"/\"kill\" ) ==\u003e true`\n*   `h:wait() ==\u003e true/nil, string, number`\n\n`h:write()` accepts strings and enqueues them to be sent to the child\nprocess' `stdin` stream when it is ready. You may also pass `proc.EOF`\nto close the `stdin` stream when all enqueued output has been sent.\nThe `h:kill()` function sends either a `SIGTERM` (requesting graceful\nshutdown) or a `SIGKILL` (for immediate shutdown) to the child\nprocess. `h:wait()` starts a small blocking event loop that will send\nenqueued data to the child process' `stdin`, read data from the\nchild's `stdout`/`stderr` streams, and/or wait for the child process\nto exit. The callback given to the `proc.spawn()` function is called\nwith the stream name (`\"stdout\"` or `\"stdin\"`) and the received data\n(or the usual error values) when output from the child is available.\nOn Lua 5.2+ you may yield from the callback function. Return values of\n`h:wait()` are the same as for `os.execute()` on recent Lua versions.\n\n\n###                           ipc.strfile                          ###\n\n```lua\nlocal strfile = require( \"ipc.strfile\" )\n```\n\nThis module is not about IPC at all. It allows you to create a\nfile-like object from a Lua string. It shares most of the code for\nfile handling with the `ipc.shm` and `ipc.mmap` modules, and it is\noften useful -- that's why it is here. It has exactly the same methods\nas the shared memory or mmap handles (except you are not allowed to\n`write`).\n\nThe following function is provided:\n\n*   `strfile.open( str ) ==\u003e handle`\n\n\n##                              Contact                             ##\n\nPhilipp Janda, siffiejoe(a)gmx.net\n\nComments and feedback are always welcome.\n\n\n##                              License                             ##\n\n**LuaIPC** is *copyrighted free software* distributed under the MIT\nlicense (the same license as Lua 5.1). The full license text follows:\n\n    LuaIPC (c) 2015, 2016 Philipp Janda\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files (the\n    \"Software\"), to deal in the Software without restriction, including\n    without limitation the rights to use, copy, modify, merge, publish,\n    distribute, sublicense, and/or sell copies of the Software, and to\n    permit persons to whom the Software is furnished to do so, subject to\n    the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY\n    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nThe `sem_timedwait()` implementation used on OSX was written by Keith\nShortridge at the Australian Astronomical Observatory. See the\ncomments in `osx/sem_timedwait.c` for details.\n\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiffiejoe%2Flua-luaipc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiffiejoe%2Flua-luaipc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiffiejoe%2Flua-luaipc/lists"}