{"id":50894078,"url":"https://github.com/pmarreck/os_counters","last_synced_at":"2026-06-15T23:01:58.405Z","repository":{"id":361972577,"uuid":"1256690709","full_name":"pmarreck/os_counters","owner":"pmarreck","description":"Cross-process atomic counters in LuaJIT: filesystem, POSIX shm, and System V IPC backends with per-OS tradeoffs","archived":false,"fork":false,"pushed_at":"2026-06-02T02:28:49.000Z","size":20,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"yolo","last_synced_at":"2026-06-02T04:14:59.488Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmarreck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-02T02:23:29.000Z","updated_at":"2026-06-02T02:28:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pmarreck/os_counters","commit_stats":null,"previous_names":["pmarreck/os_counters"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pmarreck/os_counters","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmarreck%2Fos_counters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmarreck%2Fos_counters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmarreck%2Fos_counters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmarreck%2Fos_counters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmarreck","download_url":"https://codeload.github.com/pmarreck/os_counters/tar.gz/refs/heads/yolo","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmarreck%2Fos_counters/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34383468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2026-06-15T23:01:54.850Z","updated_at":"2026-06-15T23:01:58.398Z","avatar_url":"https://github.com/pmarreck.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# os_counters\n\nCross-process **atomic counters** for the shell, implemented in [LuaJIT](https://luajit.org/),\nwith three interchangeable backends that make different OS-level tradeoffs. They share one\nCLI (`create` / `get` / `inc` / `dec` / `set` / `destroy` / `list`), so you can pick the\nbackend that fits your platform and durability needs.\n\n```sh\ncounter create hits 0     # counter == fs-counter (the default backend)\ncounter inc hits          # -\u003e 1\ncounter inc hits          # -\u003e 2\ncounter get hits          # -\u003e 2\ncounter destroy hits\n```\n\n## Backends \u0026 platform tradeoffs\n\n| Backend | Mechanism | macOS | Linux | sudo? | Notes |\n|---|---|---|---|---|---|\n| **`fs-counter`** (default, = `counter`) | file + `flock` locking under `$FS_COUNTER_DIR` (def. `${TMPDIR:-/tmp}/fs-counter`) | ✅ full | ✅ full | no | only backend with `list` + heavy concurrency coverage; portable |\n| **`posix-counter`** | POSIX shm (`shm_open`/`mmap`) | ⚠️ limited | ✅ | no | see macOS note |\n| **`sysv-counter`** | System V IPC (`shmget`/`shmat`) | ⚠️ needs sudo | ✅ | yes (macOS) | capped by `kern.sysv.shmmax` (4 MB default) |\n\nThese are real, current OS limitations (still present as of 2026), not implementation bugs:\n\n- **System V shm on macOS** caps a segment at **4 MB** by default (`kern.sysv.shmmax`,\n  tunable only via `sudo sysctl -w kern.sysv.shmmax=…`), and attaching needs elevated\n  privileges — hence `sysv-counter` requires `sudo` on macOS. On Linux it works unprivileged.\n- **POSIX shm on macOS** has a long-standing quirk: `ftruncate()` on a `shm_open` object\n  **only succeeds once** (subsequent calls fail with `EINVAL`), and there is no `/dev/shm`.\n  That makes `posix-counter` unreliable on macOS, so it is **not** the default.\n- **Filesystem locking** has none of these constraints, which is why `fs-counter` is the\n  portable default.\n\nSources: [shared memory on Linux \u0026 macOS](https://www.deepanseeralan.com/tech/playing-with-shared-memory/),\n[posix_ipc #5 — ftruncate once on macOS](https://github.com/osvenskan/posix_ipc/issues/5),\n[darwin-kernel: shm_open/mmap EINVAL](https://lists.apple.com/archives/darwin-kernel/2005/Feb/msg00079.html).\n\n## Install\n\n### Nix (flake)\n\n```sh\nnix run github:pmarreck/os_counters -- create hits 0   # runs `counter` (fs backend)\nnix profile install github:pmarreck/os_counters\n```\n\n### Manual\n\nPut `bin/` on your `PATH` (contains `fs-counter`, `posix-counter`, `sysv-counter`, and the\n`counter`→`fs-counter` symlink). `fs-counter` loads `lib/truthy.lua` relative to itself, so\nkeep `bin/` and `lib/` siblings. Requires `luajit` on `PATH`.\n\n## Development\n\n```sh\ndirenv allow      # or: nix develop\n./test                      # fs backend (default) — quick, no sudo\nCOUNTER_TYPE=posix ./test   # posix backend (best on Linux)\nCOUNTER_TYPE=sysv  ./test   # sysv backend; SKIPS cleanly if passwordless sudo is unavailable\nnix flake check             # hermetic CI check (fs backend only — what Garnix runs)\n```\n\nThe `sysv` suite uses `sudo -n` and **skips cleanly (exit 0) rather than ever prompting for\na password**, so unattended runs never hang. CI only exercises the `fs` backend because the\nsandbox has no sudo and POSIX/SysV shm behave differently there.\n\n## Layout\n\n```\nbin/fs-counter        filesystem-locking backend (the default)\nbin/posix-counter     POSIX shared-memory backend\nbin/sysv-counter      System V IPC backend\nbin/counter           -\u003e fs-counter\nlib/truthy.lua        small shared helper required by fs-counter\ntests/counter_test    unified suite, parameterized by $COUNTER_TYPE\ntests/{fs,posix,sysv}*_test  thin wrappers that set COUNTER_TYPE and exec counter_test\nflake.nix             dev shell, package, and CI check\ntest                  test runner\n```\n\n## License\n\nMIT © Peter Marreck\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmarreck%2Fos_counters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmarreck%2Fos_counters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmarreck%2Fos_counters/lists"}