
लाइव कर्नेल सिग्नल अवलोकनीयता उपकरण जो eBPF ट्रेसपॉइंट का उपयोग करके लिनक्स होस्ट पर उठाए गए प्रत्येक सिग्नल को स्ट्रीम करता है, वास्तविक समय में प्रेषक, लक्ष्य, स्वभाव, हैंडलर विलंबता और syscall रुकावटों को दिखाता है।
sigwire
tail -ffor signals. बॉक्स पर किसी भी प्रक्रिया द्वारा उठाया गया हर सिग्नल — किसने भेजा, किसको लगा, कौन सा सिग्नल, कैसे उठाया गया (kill(2), कर्नेल, एक POSIX टाइमर), क्या लक्ष्य ने इसे पकड़ा और इसके हैंडलर ने कितनी देर चला, क्या इसने एक अवरुद्ध सिस्कॉल कोEINTRके साथ फाड़ दिया — कर्नेल के सिग्नल ट्रेसपॉइंट्स से डिकोड करके लाइव आपके टर्मिनल पर स्ट्रीम किया गया। एक पीआईडी पर कोईstrace -fनहीं, कोईptraceनहीं, शामिल प्रक्रियाओं से कोई सहयोग नहीं।
sigwire कर्नेल के सिग्नल तंत्र को एक लाइव पैचबे में बदल देता है: प्रत्येक पंक्ति sender ──SIGNAL──▶ target है, गंभीरता के अनुसार रंगीन, कैसे उठाया गया इसके साथ टैग किया गया, क्या लक्ष्य ने इसे पकड़ा (और इसका हैंडलर कितनी देर चला), क्या इसने एक अवरुद्ध सिस्कॉल को बाधित किया (↯ EINTR read), जब कुछ स्पैम करता है तो ×N में संक्षिप्त, और जब यह वास्तविक घातक प्रहार होता है तो ☠ चिह्नित। एक साइड रेल यह गणना करता है कि वायर पर क्या उड़ रहा है; रुकें और एक पंक्ति चुनें पूरी तस्वीर देखने के लिए — स्वभाव, हैंडलर पता, sigaction फ़्लैग, और लक्ष्य उस समय किन सिग्नलों को ब्लॉक कर रहा था।
क्योंकि यह कर्नेल के ट्रेसपॉइंट्स को हुक करता है, किसी एक प्रक्रिया को नहीं, एक ही रन होस्ट पर हर सिग्नल को एक साथ देखता है — आपका ऐप, एक पर्यवेक्षक, कर्नेल का अपना फॉल्ट तंत्र — उनमें से कोई भी इस बात से अवगत नहीं कि उन पर नज़र रखी जा रही है।
[!TIP] हर सिग्नल के दो पहलू. sigwire दोनों
signal:signal_generate(प्रेषक का दृश्य — किसने क्या उठाया, स्विचबोर्ड लाइन) औरsignal:signal_deliver(लक्ष्य का दृश्य — क्या इसे पकड़ा, किस हैंडलर और फ़्लैग के साथ, क्या ब्लॉक कर रहा था, और क्या इसने सिस्कॉल को बाधित किया) देखता है। दो और हुक —rt_sigreturn(2)और syscall-exit ट्रेसपॉइंट — हैंडलर को टाइम करते हैं और EINTR को पकड़ते हैं। यह सब एक पंक्ति में सहसंबंधित होता है। यह विभाजन भी कारण है कि☠ fatalगणना जानबूझकर रूढ़िवादी है (देखें क्या घातक माना जाता है): जनरेशन डिलीवरी से पहले होती है, इसलिए प्रेषक पक्ष किसी सिग्नल के भाग्य को नहीं जान सकता — केवल डिलीवरी पक्ष जान सकता है, और केवल उन मामलों के लिए जो वह देखता है।
curl -fsSL https://yeet.cx | sh # install the yeet daemon (one time) yeet run github:yeet-src/sigwire # run the dashboard (the daemon does the privileged BPF load)
[Manual install guide](https://yeet.cx/docs/manual-installation) | Linux only
कॉन्फ़िगर करने के लिए कुछ नहीं — सिग्नल किसी भी बॉक्स पर लगातार बैकग्राउंड ट्रैफ़िक होते हैं, इसलिए पंक्तियाँ तुरंत शीर्ष पर आने लगती हैं। कुछ खुद उत्पन्न करना चाहते हैं? `kill -USR1 <pid>`, `Ctrl-C` एक फोरग्राउंड जॉब को, या कोई प्रबंधित रनटाइम शुरू करें और देखें कि इसका GC/शेड्यूलर अपने थ्रेड्स को पिंग करता है (`↯ EINTR futex` स्क्रॉल करता हुआ)।
## नियंत्रण
फ़ीड डिफ़ॉल्ट रूप से नवीनतम सिग्नल का अनुसरण करता है; एक पंक्ति चुनें या रोकें और डेटा नीचे बहता रहता है जबकि यह स्थिर रहता है।
| कुंजी | क्रिया |
| --- | ------ |
| `p` · `Space` | फ़ीड को रोकें / फिर से शुरू करें (पढ़ने के लिए फ़्रीज़ करें) |
| `↑`/`↓`, `k`/`j` | रुकें और एक पंक्ति का निरीक्षण करें — विवरण पैनल खोलता है |
| `/` | फ़ज़ी फ़िल्टर — प्रक्रिया, PID, सिग्नल, स्रोत, और स्वभाव से मेल खाता है; मेल खाने वाले वर्ण लाइव हाइलाइट होते हैं |
| `e` | फ़िल्टर **केवल बाधित सिस्कॉल** (`↯ EINTR` / `↺ पुनर्प्रारंभित`) |
| `s` | **सिग्नल पिकर** खोलें — किसी भी सिग्नल को म्यूट या दिखाएँ, लाइव |
| `Esc` | एक स्तर पीछे जाएँ — फ़िल्टर साफ़ करें / पिकर बंद करें / चयन हटाएँ, फिर बाहर निकलें |
| `q` | बाहर निकलें |
## आप क्या देख रहे हैं
प्रत्येक पंक्ति एक उत्पन्न सिग्नल है, सबसे नया शीर्ष पर:```
WHEN SENDER SIGNAL TARGET NOTE
now bash·4402──SIGINT───▶ node·8813 kill(2) ↯ EINTR read caught 41µs
1.2s systemd·1──────SIGTERM──▶ nginx·1291 kill(2) caught 1.2ms
3.4s kernel·8813──SIGSEGV──▶ chrome·8813 fault default ☠
4.1s postgres·507──SIGUSR1───▶ postgres·509 ×6 kill(2) caught 9µs
प्रत्येक पंक्ति एक ब्लॉक है: प्रेषक → लक्ष्य comm·pid हैं (प्रेषक वह है जिसने सिग्नल उठाया, current; लक्ष्य वह है जिसके लिए यह लक्षित है), तार बीच में सिग्नल का नाम लेकर चलता है जो गंभीरता के अनुसार रंगीन होता है, ×N एक पंक्ति में समान सिग्नल के प्रस्फोट को मोड़ता है, और दाईं ओर नोट स्रोत देता है, फिर कोई syscall व्यवधान, फिर निपटान।
प्रत्येक पंक्ति उस क्षण स्थिर हो जाती है जब इसकी डिलीवरी हल हो जाती है और फिर कभी नहीं बदलती — इसलिए एक प्रस्फोट एक स्थिर लॉग के रूप में स्क्रॉल करता है, न कि झिलमिलाते समुच्चय के रूप में।
तार गंभीरता के अनुसार रंगीन होता है उसी 256-रंग पैलेट पर जैसा कि शेष UI में:
नोट स्रोत है (kill(2), tgkill, sigqueue, timer, kernel, fault); फिर, यदि इसने एक अवरुद्ध syscall को बाधित किया, तो ↯ EINTR read (या ↺ restarted read जब SA_RESTART ने इसे स्वचालित रूप से फिर से शुरू किया); फिर निपटान — caught 41µs (एक हैंडलर चला, और इसमें कितना समय लगा), default (कोई हैंडलर नहीं, डिफ़ॉल्ट कार्रवाई लागू हुई), या ⊘ ignored। एक ☠ एक वास्तविक घातक प्रहार को चिह्नित करता है (देखें क्या घातक माना जाता है)।
[!NOTE]
↯ EINTRदेखने वाला है। एक सिग्नल जो तब आता है जब एक थ्रेड एक धीमी syscall (read,poll,accept,futex,nanosleep, …) में रुका होता है, उसे बाहर खींच लेता है: syscall-1/EINTRलौटाता है और, जब तक हैंडलर नेSA_RESTARTसेट नहीं किया, यह फिर से शुरू नहीं होता — ऐप को दोबारा प्रयास करना होता है। इसे भूलना एक क्लासिक, क्रोधित करने वाला, समय-निर्भर बग है ("मेरीread()विफल क्यों हुई एक बार?")। sigwire इसे लाइव होते हुए दिखाता है, और किस syscall पर चोट लगी। दबाएंeबाकी सब कुछ छिपाने के लिए और केवल इंटरप्ट देखने के लिए।
दाईं ओर की पटरी समुच्चय दृश्य है: मात्रा के अनुसार शीर्ष सिग्नल, स्रोत के अनुसार एक विभाजन, और डिलीवरी का गणना — कितने सिग्नल पकड़े गए बनाम उनका डिफ़ॉल्ट लगा बनाम अनदेखा किया गया।
दबाएं ↑/↓ (या p) फ़ीड को फ़्रीज़ करने और एक पंक्ति चुनने के लिए; पटरी एक विस्तार पैनल में बदल जाती है जिसमें डिलीवरी पक्ष उस सटीक सिग्नल के बारे में जो कुछ भी जानता है:```
SIGNAL
SIGUSR1 (10) user
from ctarget·3980913
to ctarget·3980913
RAISED
via tgkill
code SI_TKILL
scope thread
result delivered
DELIVERY
handled caught
syscall EINTR ← read
handler 0x55f0a1c3
ran 3.0ms
flags SA_SIGINFO
TARGET BLOCKS
SIGINT SIGQUIT SIGTERM
- **handled** — `caught` (उपयोगकर्ता स्थान हैंडलर चला), `default` (→ डिफ़ॉल्ट कार्रवाई: समाप्त करें / कोर डंप / रोकें / अनदेखा करें), या `ignored`।
- **syscall** — यदि इस सिग्नल ने एक अवरुद्ध syscall को बाधित किया: `EINTR ← read` (उपयोगकर्ता स्थान ने `EINTR` देखा) या `restarted read` (`SA_RESTART` ने इसे पारदर्शी रूप से फिर से शुरू किया)।
- **ran** — हैंडलर ने कितने समय तक निष्पादित किया, डिलीवरी से `rt_sigreturn(2)` तक मापा गया जो इसे समाप्त करता है। (जो रनटाइम C हैंडलर में केवल एक फ्लैग सेट करते हैं और बाद में वास्तविक कार्य करते हैं — CPython, Go — यहाँ बहुत छोटा समय दिखाते हैं; यह उनकी विशेषता है, sigwire की नहीं।)
- **flags** — हैंडलर पर `sigaction` फ्लैग (`SA_RESTART`, `SA_SIGINFO`, `SA_NODEFER`, …)।
- **TARGET BLOCKS** — डिलीवरी के समय लक्ष्य द्वारा अवरुद्ध सिग्नल (इसका `sigprocmask`), सीधे इसके `task_struct` से प्राप्त।
`Esc` इंस्पेक्टर को बंद करता है; `p` लाइव फ़ीड फिर से शुरू करता है।
## फेटल के रूप में क्या गिना जाता है
`☠ fatal` काउंटर और `☠` पंक्ति बैज जानबूझकर सख्त हैं। क्योंकि `signal_generate` *जनरेशन* के समय फायर करता है, sigwire यह नहीं देख सकता कि लक्ष्य ने हैंडलर स्थापित किया है या नहीं — एक `SIGTERM` पकड़ा जा सकता है और साफ शटडाउन में बदल दिया जा सकता है, या पूरी तरह से अनदेखा किया जा सकता है। इसलिए यह केवल तभी मौत गिनता है जब यह स्पष्ट हो:
- **`SIGKILL`** वितरित — अट्रैपेबल, अनदेखा नहीं किया जा सकता, हमेशा फेटल; **या**
- एक **कोर-डंपिंग सिग्नल** (`SEGV`/`BUS`/`ABRT`/`ILL`/`FPE`/`TRAP`/`SYS`/`QUIT`) जिसे **कर्नेल ने खुद उठाया** (एक सिंक्रोनस फॉल्ट, न कि उपयोगकर्ता स्थान का `kill`)।
बाकी सब कुछ — `systemd` से `SIGTERM`, आपके `Ctrl-C` से `SIGINT`, रनटाइम का अपने थ्रेड्स को `SIGPWR` — दिखाया और रंगीन किया जाता है, लेकिन मौत के रूप में नहीं गिना जाता, क्योंकि यह शायद मौत नहीं था।
## सिग्नल पिकर (एक लाइव कर्नेल नॉब)
तीन सिग्नल किसी भी व्यस्त बॉक्स पर शुद्ध पृष्ठभूमि गूंज हैं: `SIGCHLD` (हर चाइल्ड रीप), `SIGURG` (Go का एसिंक-प्रीइम्प्शन हार्टबीट), और `SIGWINCH` (टर्मिनल रिसाइज़, हर फोरग्राउंड प्रक्रिया को प्रसारित)। sigwire डिफ़ॉल्ट रूप से इन तीनों को **कर्नेल में** म्यूट करता है ताकि फ़ीड दिलचस्प ट्रैफ़िक हो — लेकिन कौन से सिग्नल शोर हैं यह आपका कॉल है।
`s` दबाएं **सिग्नल पिकर** खोलने के लिए: एक मोडल लिस्ट जिसमें हर सिग्नल का लाइव गंभीरता रंग और आपने कितने देखे हैं, प्रत्येक `shown` और `muted` के बीच टॉगल करने योग्य। एक पर **एरो** (या **इसका नंबर टाइप करें** — `1`, `5` → 15 पर जाएं) और `space` दबाएं, और वह सिग्नल तुरंत फ्लिप हो जाता है। `a` उन्हें **सभी** एक साथ टॉगल करता है। टाइटलबार का `muted` काउंट ट्रैक करता है कि कितने छिपे हैं।
यह डेमो का दो-तरफा हिस्सा है: म्यूट मास्क चल रहे BPF प्रोग्राम के `.data` सेक्शन में एक `__u64` ग्लोबल है, और एक पंक्ति टॉगल करने से `DataSec.patch()` के माध्यम से मैचिंग बिट पैच होता है जबकि प्रोग्राम चलता रहता है। कर्नेल म्यूट किए गए सिग्नलों को रिंग बफर तक पहुंचने से पहले ही गिरा देता है, इसलिए म्यूट करने से आपको कुछ खर्च नहीं होता — और अनम्यूट करने से बिना किसी रीलोड के मिड-स्ट्रीम में एक सिग्नल वापस आ जाता है।
## यह कैसे काम करता है
कोर है [`src/bpf/sigwire.bpf.c`](https://github.com/yeet-src/sigwire/blob/HEAD/src/bpf/sigwire.bpf.c) + [`src/bpf/deliver.bpf.c`](https://github.com/yeet-src/sigwire/blob/HEAD/src/bpf/deliver.bpf.c) (कर्नेल, एक ऑब्जेक्ट में लिंक) और [`src/probes/sigwire.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/probes/sigwire.js) (उपयोगकर्ता स्थान)। सब कुछ `(target tid, signal)` द्वारा सहसंबद्ध है।
### BPF पक्ष
दो स्रोत फ़ाइलें एक लोड करने योग्य ऑब्जेक्ट, `bin/probe.bpf.o` में लिंक होती हैं, जिसमें चार ट्रेसपॉइंट प्रोग्राम हैं:
| प्रोग्राम | किससे जुड़ा | क्या कैप्चर करता है |
|---|---|---|
| `on_signal_generate` | `signal:signal_generate` | भेजने वाला (`current`) + लक्ष्य (`comm`/`pid`), सिग्नल, `si_code`, `group` फ्लैग, `result` — कर्नेल में ही गिरा दिया जाता है यदि सिग्नल का बिट लाइव `mute_mask` में सेट है |
| `on_signal_deliver` | `signal:signal_deliver` | लक्ष्य का डिस्पोज़िशन (`sa_handler`), `sa_flags`, और — `task_struct` से — इसका `blocked` sigset; हैंडलर टाइमिंग के लिए डिलीवरी स्टैम्प करता है |
| (rt_sigreturn) | `syscalls:sys_enter_rt_sigreturn` | हैंडलर के रन टाइम के लिए स्टैम्प की गई डिलीवरी से अंतर करता है |
| (sys_exit) | `raw_syscalls:sys_exit` | दुर्लभ `-ERESTART*` रिटर्न को रिकॉर्ड करता है ताकि अगला `signal_deliver` इसे `EINTR`/`restarted` + बाधित syscall नंबर में हल करे |
मैप्स कर्नेल को उपयोगकर्ता स्थान से जोड़ते हैं:
- `events` — `RINGBUF`, प्रति जनरेशन एक `signal_event`।
- `dispatch` — `RINGBUF`, प्रति डिलीवरी / हैंडलर-रिटर्न एक `dispatch_event`।
- `mute_mask` — `.data` सेक्शन में एक `__u64` ग्लोबल; पिकर कर्नेल में सिग्नल गिराने के लिए अलग-अलग बिट्स पैच करता है।
- `handler_start` / `restart_pending` — tid द्वारा की गई `HASH`, प्रति-थ्रेड स्क्रैच जो एक डिलीवरी को उसके `rt_sigreturn` से जोड़ता है, और एक syscall के `-ERESTART*` एग्जिट को उसके बाद की डिलीवरी से जोड़ता है।
### JS पक्ष
| फ़ाइल | जिम्मेदारी |
|---|---|
| [`src/probes/probe.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/probes/probe.js) | `bin/probe.bpf.o` को एक बार लोड करता है, मैप्स बाइंड करता है, प्रोग्राम शुरू करता है (वे ऑटो-अटैच होते हैं) |
| [`src/probes/sigwire.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/probes/sigwire.js) | एकमात्र BPF-जागरूक डेटा मॉड्यूल: दोनों रिंग बफ़र्स को गणनाओं के साथ रोलिंग फ़ीड में मोड़ता है, डिलीवरी को जनरेशन पर सहसंबद्ध करता है, म्यूट-मास्क नॉब का मालिक है — `feed`, `visible`, `muteMask` सिग्नलों को एक्सपोज़ करता है |
| [`src/main.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/main.jsx) | कम्पोज़िशन रूट: इनपुट, सेलेक्शन, रिस्पॉन्सिव लेआउट (रेल संकीर्ण टर्मिनलों पर छिप जाती है), `mount` |
| [`src/components/feed.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/feed.jsx) | स्विचबोर्ड: `sender ──SIG──▶ target`, डिस्पोज़िशन/लेटेंसी, बैज, टिंट, कोलेसिंग |
| [`src/components/tally.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/tally.jsx) | साइड रेल — शीर्ष सिग्नल, स्रोत द्वारा ब्रेकडाउन, डिलीवरी गणना |
| [`src/components/detail.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/detail.jsx) | इंस्पेक्टर — प्रति-सिग्नल डिस्पोज़िशन, हैंडलर, फ्लैग, ब्लॉक की गई मास्क |
| [`src/components/picker.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/picker.jsx) | सिग्नल पिकर मोडल — कर्नेल म्यूट मास्क के माध्यम से प्रत्येक सिग्नल को म्यूट/शो करता है |
| [`src/components/titlebar.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/titlebar.jsx) | ब्रांड, लाइव रेट, कुल, `☠ fatal` काउंटर, म्यूट काउंट, लाइव/पॉज़्ड |
| [`src/components/footer.jsx`](https://github.com/yeet-src/sigwire/blob/HEAD/src/components/footer.jsx) | कुंजी संकेत और लाइव फ़िल्टर प्रॉम्प्ट |
| [`src/lib/signals.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/lib/signals.js) | सत्य का एकमात्र स्रोत: नाम, गंभीरता, रंग, `si_code` → स्रोत, डिस्पोज़िशन, फ्लैग, मास्क डीकोड, घातकता |
| [`src/lib/format.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/lib/format.js) | शुद्ध फ़ॉर्मेटर — पैडिंग, ट्रंकेशन, `ago()`, अवधि, कॉम्पैक्ट काउंट |
| [`src/lib/fuzzy.js`](https://github.com/yeet-src/sigwire/blob/HEAD/src/lib/fuzzy.js) | प्रक्रिया + pid + सिग्नल + स्रोत + डिस्पोज़िशन पर अनुक्रम फ़ज़ी मैच |
मॉडल एक रोलिंग **जनरेटेड सिग्नलों की फ़ीड** है, समान दोहराव को `×N` पंक्तियों में समाहित करता है। एक सिग्नल की जनरेशन पंक्ति उस समय फ़्रीज़ हो जाती है जब उसकी डिलीवरी हल हो जाती है — इसलिए स्क्रीन पर पहले से मौजूद पंक्ति कभी नहीं बदलती या कूदती नहीं है। 120 ms का विंडो टाइमर प्रति फ्रेम एक स्नैपशॉट प्रकाशित करता है, इसलिए एक व्यस्त रिंग बफर की लागत एक री-रेंडर है, हजारों नहीं।
### ट्रेसपॉइंट क्यों, `strace`/`ptrace` क्यों नहीं
`strace -f` एक प्रक्रिया ट्री का अनुसरण करता है और हर घटना पर ट्रेसी को रोकता है; `ptrace` प्रति-लक्ष्य और आक्रामक है। सिग्नल ट्रेसपॉइंट वह सीम हैं जहां *कर्नेल* एक सिग्नल उठाता और वितरित करता है, *हर* प्रक्रिया के लिए, बिना किसी प्रति-ऐप सेटअप और बिना किसी को रोके। जनरेशन ↔ डिलीवरी ↔ `rt_sigreturn` को जोड़ने से भेजने वाले/लक्ष्य जोड़ी, डिस्पोज़िशन, प्रति-हैंडलर लेटेंसी, और EINTR निर्णय प्राप्त होता है जो एक सिग्नल के पूरे जीवन को एक साथ बांधता है।
## विभिन्न कर्नेल पर परीक्षण
`make veristat` **आपके** कर्नेल पर `bin/probe.bpf.o` को veristat के साथ लोड करता है — एक त्वरित जांच कि हर प्रोग्राम वेरिफायर पास करता है, साथ ही प्रति-प्रोग्राम जटिलता (insns/states)। BPF लोड करने के लिए विशेषाधिकारों की आवश्यकता है, इसलिए `sudo` का उपयोग करें।
एक प्रोग्राम जो आपके लैपटॉप पर लोड होता है, वह पुराने कर्नेल के वेरिफायर द्वारा अस्वीकार किया जा सकता है। [`.github/workflows/kernel-matrix.yml`](https://github.com/yeet-src/sigwire/blob/HEAD/.github/workflows/kernel-matrix.yml) इससे बचाता है: अपने मैट्रिक्स में प्रत्येक कर्नेल के लिए यह ऑब्जेक्ट बनाता है, उस कर्नेल को एक VM में बूट करता है ([cilium's little-vm-helper](https://github.com/cilium/little-vm-helper), `quay.io/lvh-images` से चित्र), और उसके खिलाफ वेंडर्ड स्टैटिक **veristat** चलाता है — यदि वेरिफायर किसी प्रोग्राम को अस्वीकार करता है तो कार्य विफल हो जाता है, और प्रति-कर्नेल परिणामों को एक ✅/❌ ग्रिड में पिवट करता है। VM के अंदर का गेट [`build/verify-kernel.sh`](https://github.com/yeet-src/sigwire/blob/HEAD/build/verify-kernel.sh) है।
उसी मैट्रिक्स को स्थानीय रूप से (Linux + KVM) चलाएँ `make veristat-matrix` के साथ — यह `lvh` + QEMU के साथ कर्नेल चित्रों को बूट करता है और एक `ok`/`FAIL` ग्रिड प्रिंट करता है। कर्नेल चुनें `make veristat-matrix KERNELS="6.6 bpf-next"` के साथ।
## आवश्यकताएँ
> [!IMPORTANT]
> - **BTF वाला एक Linux कर्नेल** (`CONFIG_DEBUG_INFO_BTF`) CO-RE के लिए — `bpftool` इससे `src/bpf/include/vmlinux.h` उत्पन्न करता है। वर्तमान Arch, Fedora, Ubuntu, और Debian पर डिफ़ॉल्ट (हर मुख्यधारा डिस्ट्रो कर्नेल ~5.4 के बाद से)।
> - **yeet डेमन**, जो विशेषाधिकार प्राप्त BPF लोड करता है। BPF क्षमताओं को एक डेमोनाइज़्ड प्रक्रिया को सौंप दिया जाता है, ताकि `sigwire` स्वयं अविशेषाधिकार प्राप्त चलता है। `curl -fsSL https://yeet.cx | sh` इसे स्थापित करता है।
>
> स्रोत से बनाने के लिए आपको `clang` और `bpftool` की भी आवश्यकता है — लेकिन वेंडर्ड स्टैटिक टूलचेन उनकी आपूर्ति करता है, इसलिए आपको सिस्टम C/BPF टूलचेन की आवश्यकता नहीं है। कोई node/npm नहीं: esbuild भी वेंडर्ड है और प्रोजेक्ट में कोई तृतीय-पक्ष डिपेंडेंसी नहीं है।
## ईमानदार चेतावनियाँ
> [!NOTE]
> `sigwire` अवलोकनीयता है, प्रवर्तन नहीं। यह आपको दिखाता है कि क्या उठाया गया; यह किसी सिग्नल को ब्लॉक, विलंब या बदलता नहीं है।
- **एक पंक्ति एक *उठाया गया* सिग्नल है।** स्विचबोर्ड लाइन जनरेशन से आती है; लक्ष्य इसे पकड़ सकता है, ब्लॉक कर सकता है, या पहले ही बाहर निकल चुका हो सकता है। डिस्पोज़िशन/हैंडलर/मास्क कॉलम *डिलीवरी* पक्ष से आते हैं और केवल तभी भरते हैं जब कर्नेल वास्तव में इसे वितरित करता है — एक अवरुद्ध या अभी भी लंबित सिग्नल कोई डिस्पोज़िशन नहीं दिखाता है। [फेटल के रूप में क्या गिना जाता है](#what-counts-as-fatal) देखें।
- **सहसंबंध सर्वोत्तम प्रयास है।** जनरेशन और डिलीवरी बिना किसी साझा आईडी के अलग-अलग ट्रेसपॉइंट हैं, जो एक समय विंडो के भीतर `(target tid, signal)` पर मिलान किए जाते हैं। एक ही थ्रेड को एक ही सिग्नल के तूफान के तहत जोड़ी धुंधली हो सकती है; यह अत्यधिक सामान्य मामले में सही है।
- **हैंडलर टाइमिंग कर्नेल के फ्रेम को मापता है, आपके इरादे को नहीं।** `ran` डिलीवरी → `rt_sigreturn` है। एक हैंडलर जो केवल एक फ्लैग सेट करता है (CPython, Go का रनटाइम) माइक्रोसेकंड में लौटता है, भले ही "वास्तविक" कार्य बाद में इवेंट लूप में हो — सटीक, बस वह नहीं जो आप उम्मीद कर सकते हैं।
- **EINTR डिटेक्शन हर syscall एग्जिट देखता है।** बाधित syscalls को पकड़ने का मतलब है `raw_syscalls:sys_exit` से जुड़ना, जो सिस्टम-वाइड हर syscall रिटर्न पर फायर करता है (हैंडलर दुर्लभ `-ERESTART*` कोड को छोड़कर सभी पर तुरंत बाहर निकलता है, इसलिए जोड़ा गया खर्च प्रति syscall कुछ निर्देश है — लेकिन यह शून्य नहीं है)। Syscall *नाम* एक x86-64 तालिका है; अन्य आर्किटेक्चर कच्चा syscall नंबर दिखाते हैं।
- **कर्नेल सिग्नल का भेजने वाला `current` है।** एक सिंक्रोनस फॉल्ट (`SIGSEGV` खराब एक्सेस से) के लिए यह फॉल्टिंग कार्य ही है — सही और उपयोगी। एक एसिंक्रोनस कर्नेल सिग्नल के लिए, `current` वह कार्य है जो कर्नेल द्वारा इसे उठाने पर चल रहा था, जो एक संकेत है, न कि सुसमाचार।
- **रीयल-टाइम सिग्नल नंबरिंग नाममात्र है।** `SIGRTMIN+n` कच्चे ऑफसेट द्वारा दिखाया गया है; लाइब्रेरीज़ अपने उपयोग के लिए निचले कुछ को आरक्षित करती हैं।
- **`comm` 16 बाइट्स है।** लंबी प्रक्रिया के नाम कर्नेल द्वारा काटे जाते हैं, sigwire द्वारा नहीं।
## सामुदायिक प्रश्न
**क्या यह ट्रेस की गई प्रक्रियाओं को धीमा कर देता है?**
कोई सार्थक ओवरहेड नहीं। ट्रेसपॉइंट प्रोग्राम निष्क्रिय हैं; लागत प्रति सिग्नल एक बाउंडेड रिंग-बफर राइट है (और EINTR डिटेक्शन के लिए प्रति syscall एग्जिट कुछ निर्देश), और यदि उपयोगकर्ता स्थान पीछे रह जाता है तो रिंग बफर ब्लॉक करने के बजाय गिरा देता है।
**क्या यह उस प्रक्रिया पर लक्षित सिग्नल दिखाएगा जो पहले से चल रही थी जब मैं इसे शुरू करूं?**
हाँ। ट्रेसपॉइंट उस क्षण से हर सिग्नल के लिए फायर करते हैं जब sigwire जुड़ता है, भले ही भेजने वाला या लक्ष्य कब शुरू हुआ — कोई प्रति-प्रक्रिया स्थिति नहीं है जो छूट गई हो।
**क्या यह किसी भी प्रक्रिया के लिए काम करता है, या केवल एक के लिए?**
होस्ट पर कोई भी प्रक्रिया, सभी एक साथ — भेजने वाला/लक्ष्य गटर उन्हें अलग करता है। यह पूरी मशीन का सिग्नल ट्रैफ़िक है, एक पिड नहीं।
**क्या मैं फ़ीड निर्यात कर सकता हूँ?**
अंतर्निहित नहीं। `probes/sigwire.js` में `RingBuf.subscribe` कॉलबैक प्रत्येक डिकोडेड रिकॉर्ड रखते हैं, इसलिए एक JSON/HTTP/Kafka सिंक वहाँ एक शाखा है। एक प्रबंधित पाइपलाइन स्थापित करने के लिए, [हमसे संपर्क करें](https://yeet.cx/)।
## स्रोत से बनाना```sh
make # clang + bpftool → bin/probe.bpf.o ; esbuild → src/index.jsx
make bpf # just the BPF object
make bundle # just the JS bundle
make clean # remove build artifacts
Then yeet run . स्थानीय बिल्ड चलाता है। make दो स्वतंत्र कंपाइलर चलाता है: clang + bpftool src/bpf/*.bpf.c को लोड करने योग्य ऑब्जेक्ट bin/probe.bpf.o में लिंक करता है; esbuild src/main.jsx को src/index.jsx में बंडल करता है, tsconfig paths के माध्यम से @/ (स्रोत रूट) और #/ (प्रोजेक्ट रूट) बंडल-टाइम उपनामों को हल करता है और yeet:* बिल्ट-इन को बाहरी छोड़ देता है। दोनों कंपाइलर एक विक्रेता-प्रदत्त स्थैतिक टूलचेन से आते हैं, इसलिए बिल्ड को किसी सिस्टम C/BPF टूलचेन और न ही node/npm की आवश्यकता होती है। जनरेट किए गए vmlinux.h, src/index.jsx, और bin/*.bpf.o बिल्ड आर्टिफैक्ट हैं।
क्योंकि उपनाम केवल बंडल-टाइम होते हैं, रनटाइम BPF ऑब्जेक्ट को किसी उपनाम के बजाय import.meta.dirname से ढूंढता है। yeet डैशबोर्ड-लेखन गाइड के लिए AGENTS.md (उर्फ CLAUDE.md) देखें।
दोहरी BSD/GPL। BPF प्रोग्राम src/bpf/sigwire.bpf.c में char LICENSE[] SEC("license") = "Dual BSD/GPL" घोषित करता है, जिसकी कर्नेल को इसके द्वारा उपयोग किए जाने वाले हेल्पर्स के लिए आवश्यकता होती है।
yeet के साथ निर्मित, Linux पर eBPF प्रोग्राम लिखने के लिए एक JS रनटाइम। Discord पर हमसे जुड़ें।
| गंभीरता | सिग्नल | रंग |
|---|
| मार | SIGKILL | गर्म लाल |
| घातक (कोर डंपिंग) | SEGV BUS ABRT ILL FPE TRAP SYS QUIT | लाल |
| समाप्त करने वाला | TERM INT HUP PIPE ALRM … | एम्बर |
| कार्य नियंत्रण | STOP TSTP TTIN TTOU | पीला |
| जारी रखें | CONT | हरा |
| उपयोगकर्ता | USR1 USR2 | सियान |
| रीयल-टाइम | SIGRTMIN+n | बैंगनी |
| गृह व्यवस्था | CHLD URG WINCH … | ग्रे |