tkill(2)

πŸ’– tkill, tgkill β€” send a signal to a thread πŸ’–

okay bestie, grab your strawberry lemonade πŸ“ because we're diving into the System Calls Manual β€” yes, the System Calls Manual, that's the section this page lives in β€” and we're talking about the two little syscalls that let you poke one specific thread instead of just yelling at the whole process. no cap, this is niche but iconic πŸ‘‘


✨ NAME ✨

tkill, tgkill β€” send a signal to a thread


πŸ“š LIBRARY πŸ“š

Standard C library (libc, -lc)


πŸŽ€ SYNOPSIS πŸŽ€

#include <signal.h>           /* Definition of SIG* constants */
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>

[[deprecated]] int syscall(SYS_tkill, pid_t tid, int sig);

#include <signal.h>

int tgkill(pid_t tgid, pid_t tid, int sig);
⚠️ okay so heads up: glibc provides no wrapper for tkill(), which means you're forced to go through syscall(2). not me having to write syscall(SYS_tkill, ...) by hand like it's 2003 😭

πŸ¦‹ DESCRIPTION πŸ¦‹

tgkill() sends the signal sig to the thread with the thread ID tid in the thread group tgid. it's giving precision targeting bestie 🎯

(by contrast, kill(2) can only send a signal to a process β€” a.k.a. a thread group β€” as a whole, and the signal gets delivered to some arbitrary thread inside that process. lowkey chaotic, fr fr.)

tkill() is an obsolete predecessor to tgkill(). it lets you specify the target thread ID and nothing else, which means the wrong thread might get signaled if a thread terminates and its thread ID gets recycled πŸ’€ avoid using this system call. like, genuinely. i'm not being dramatic for once.

these are the raw system call interfaces, meant for internal thread library use. iykyk 🧚


πŸ‘‘ RETURN VALUE πŸ‘‘

  • on success, 0 is returned. slay ✨
  • on error, -1 is returned, and errno is set to indicate the error 😭

πŸ”₯ ERRORS πŸ”₯

  • EAGAIN β€” the RLIMIT_SIGPENDING resource limit was reached and sig is a real-time signal.
  • EAGAIN β€” insufficient kernel memory was available and sig is a real-time signal.
  • EINVAL β€” an invalid thread ID, thread group ID, or signal was specified.
  • EPERM β€” permission denied. for the permissions you actually need, go check kill(2).
  • ESRCH β€” no process with the specified thread ID (and thread group ID) exists.

(not two EAGAIN entries bestie, that's not a typo, that's literally what the page says πŸ’…)


🌈 STANDARDS 🌈

Linux. that's it. that's the section.


🌸 HISTORY 🌸

  • tkill() β€” Linux 2.4.19 / 2.5.4.
  • tgkill() β€” Linux 2.5.75, glibc 2.30.

πŸ’œ NOTES πŸ’œ

for an explanation of what thread groups even are, see the description of CLONE_THREAD in clone(2). that's the lore drop you need 🫢


⭐ SEE ALSO ⭐


and that's the whole vibe check, bestie πŸŽ€ this page came from Linux man-pages 6.20, dated 2026-02-08, and it's filed under tkill(2). go signal a thread responsibly, mwah πŸ’–

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms