- How to print the current thread stack trace inside the Linux kernel?
- 2 Answers 2
- How to print the current thread stack trace inside the linux kernel?
- Method 1: dump_stack()
- Method 2: dump_backtrace()
- Method 3: show_stack()
- Method 4: print_stack_trace()
- How to know where a program is stuck in linux?
- 5 Answers 5
How to print the current thread stack trace inside the Linux kernel?
I would like to be able to print the stack trace of a thread in the Linux kernel. In details: I want to add code to specific functions (e.g. swap_writepage() ) that will print the complete stack trace of the thread where this function is being called. Something like this:
int swap_writepage(struct page *page, struct writeback_control *wbc) < /* code goes here to print stack trace */ int ret = 0; if (try_to_free_swap(page)) < unlock_page(page); goto out; >if (frontswap_store(page) == 0) < set_page_writeback(page); unlock_page(page); end_page_writeback(page); goto out; >ret = __swap_writepage(page, wbc, end_swap_bio_write); out: return ret; >
2 Answers 2
Linux kernel has very well known function called dump_stack() here, which prints the content of the stack. Place it in your function according to see stack info.
@rakib is exactly right of course.
In addition, I’d like to point out that one can define simple and elegant macros that help print debug info as and when required. Over the years, I’ve put these macros and conveneince routines into a header file; you can check it out and download it here: «A Header of Convenience».
There are macros / functions to:
- make debug prints along with funcname / line# info (via the usual printk() or trace_printk()) and only if DEBUG mode is On
- dump the kernel-mode stack
- print the current context (process or interrupt along with flags in the form that ftrace uses)
- a simple assert() macro (!)
- a cpu-intensive DELAY_LOOP (useful for test rigs that must spin on the processor)
- an equivalent to usermode sleep functionality
- a function to calculate the time delta given two timestamps (timeval structs)
- convert decimal to binary, and
- a few more.
How to print the current thread stack trace inside the linux kernel?
Printing the current thread stack trace is a useful debugging technique that can help diagnose the root cause of a problem in the Linux kernel. The stack trace provides a record of the function calls that are executed within the current thread, from the point of entry to the current point of execution. This information can be invaluable when trying to identify the source of a bug, crash, or performance issue. In this article, we will explore different methods for printing the current thread stack trace in the Linux kernel.
Method 1: dump_stack()
To print the current thread stack trace inside the Linux kernel, you can use the dump_stack() function. Here’s how to use it:
This will print the current thread’s stack trace to the kernel log.
Here’s an example of how to use dump_stack() in a kernel module:
#include #include #include static int __init my_module_init(void) printk(KERN_INFO "Hello, world!\n"); dump_stack(); return 0; > static void __exit my_module_exit(void) printk(KERN_INFO "Goodbye, world!\n"); > module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example Linux module.");
When you load this module, it will print «Hello, world!» to the kernel log, followed by the current thread’s stack trace.
You can also use dump_stack() in kernel code outside of a module. For example, here’s how to use it in a system call:
SYSCALL_DEFINE0(my_syscall) printk(KERN_INFO "my_syscall called\n"); dump_stack(); return 0; >
This system call will print «my_syscall called» to the kernel log, followed by the current thread’s stack trace.
In summary, to print the current thread stack trace inside the Linux kernel, you can use the dump_stack() function. Simply include the necessary header files and call the function. You can use it in a kernel module or in kernel code outside of a module, such as in a system call.
Method 2: dump_backtrace()
To print the current thread stack trace inside the Linux kernel, you can use the dump_backtrace() function. Here are the steps to do it:
#include #include #include #include
void my_function(void) dump_backtrace(current); >
This will print the stack trace for the current thread.
- If you want to print the stack trace for a specific thread, you can pass the thread’s task_struct to the dump_backtrace() function:
void my_function(struct task_struct *task) dump_backtrace(task); >
- If you want to print the stack trace for a thread other than the current one, you will need to acquire the thread’s task_struct first. Here’s an example:
void my_function(void) struct task_struct *task; task = pid_task(find_vpid(pid), PIDTYPE_PID); dump_backtrace(task); >
In this example, pid is the process ID of the thread you want to print the stack trace for.
That’s it! These examples should help you print the current thread stack trace inside the Linux kernel using the dump_backtrace() function.
Method 3: show_stack()
To print the current thread stack trace inside the Linux kernel, you can use the show_stack() function. This function is defined in the kernel/stacktrace.c file and prints the current stack trace to the kernel log buffer.
Here is an example of how to use show_stack() :
#include #include static int my_func(void) /* Print the current stack trace */ show_stack(NULL); return 0; > static int __init my_init(void) printk(KERN_INFO "Hello, world!\n"); my_func(); return 0; > static void __exit my_exit(void) printk(KERN_INFO "Goodbye, world!\n"); > module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple module that prints the current stack trace");
In this example, we define a function my_func() that calls show_stack() to print the current stack trace. We then call my_func() from the module’s initialization function my_init() . Finally, we define a module exit function my_exit() that prints a goodbye message to the kernel log buffer.
To build and load this module, save the code to a file named my_module.c and run the following commands:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules sudo insmod my_module.ko
You can then view the kernel log buffer to see the stack trace by running:
This will display the kernel log buffer, including the stack trace printed by show_stack() .
Method 4: print_stack_trace()
To print the current thread stack trace inside the Linux kernel, you can use the print_stack_trace() function. Here’s how to do it:
struct task_struct *task = current; struct stack_trace trace; memset(&trace, 0, sizeof(trace)); trace.nr_entries = 0; trace.max_entries = 10; trace.entries = kmalloc(trace.max_entries * sizeof(struct stack_trace_entry), GFP_KERNEL); if (trace.entries) save_stack_trace_tsk(task, &trace); print_stack_trace(&trace, 0); kfree(trace.entries); >
In this example, we first get a pointer to the current task using the current macro. We then create a stack_trace structure and initialize it with memset() . We set the maximum number of entries to 10 and allocate memory for the entries using kmalloc() .
If the allocation is successful, we call save_stack_trace_tsk() to fill the trace structure with the stack trace of the current task. Finally, we call print_stack_trace() to print the stack trace to the kernel log.
Note that print_stack_trace() takes a second argument that specifies the number of frames to skip at the beginning of the trace. In this example, we pass 0 to print the entire trace.
That’s it! With these few lines of code, you can print the current thread stack trace inside the Linux kernel using print_stack_trace() .
How to know where a program is stuck in linux?
and it used to show the whole callstack of the process. Is there any equivalent of procstack in linux/ubuntu?
5 Answers 5
My first step would be to run strace on the process, best
if your process ID is 12345. This will show you all syscalls the program is doing. How to strace a process tells you more.
If you insist on getting a stacktrace, google tells me the equivalent is pstack. But as I do not have it installed I use gdb:
tweedleburg:~ # sleep 3600 & [2] 2621 tweedleburg:~ # gdb (gdb) attach 2621 (gdb) bt #0 0x00007feda374e6b0 in __nanosleep_nocancel () from /lib64/libc.so.6 #1 0x0000000000403ee7 in ?? () #2 0x0000000000403d70 in ?? () #3 0x000000000040185d in ?? () #4 0x00007feda36b8b05 in __libc_start_main () from /lib64/libc.so.6 #5 0x0000000000401969 in ?? () (gdb)
Two answers have been given for finding the stack trace of a program (remember to install debugging symbols first!). If you want to find out where a system call got stuck, examine /proc/PID/stack , which lists the kernel stack. Example:
$ cat /proc/self/stack [] save_stack_trace_tsk+0x22/0x40 [] proc_pid_stack+0x8e/0xe0 [] proc_single_show+0x50/0x90 [] seq_read+0xe0/0x3e0 [] vfs_read+0x94/0x180 [] SyS_read+0x49/0xb0 [] system_call_fastpath+0x16/0x1b [] 0xffffffffffffffff
NOTE: per man7.org/linux/man-pages/man5/proc.5.html . «/proc/[pid]/stack (since Linux 2.6.29) This file provides a symbolic trace of the function calls in this process’s kernel stack. This file is provided only if the kernel was built with the CONFIG_STACKTRACE configuration option.«
Also note access to that file is limited to superuser or the process itself (at least on the systems I’ve tried).
See also /proc/pid/wchan and the WCHAN column in ps -l output or ps -o wchan for the top of that stack. (the ps part works on many Unices, but is not always (often) useful in itself).
On most unix systems, you can use GDB.
There’s also pstack (not a standard utility, you’ll probably have to install it manually). It looks like an equivalent of AIX’s procstack . But on my Debian wheezy amd64, it seems to always error out. On i386, for a program compiled without debugging symbols, it doesn’t print any symbol, not even from libraries for which debugging symbols are available.
You can also use strace -p1234 to see the system calls performed by the process.
pstack seems to be throwing errors everytime. Something like root@sarai:~# pstack 6312 6312: /usr/bin/python /usr/bin/twistd -n —uid=maas —gid=maas —pidfile=/run/maas-pserv.pid —logfile=/dev/null maas-pserv —conf. (No symbols found) crawl: Input/output error Error tracing through process 6312
You want eu-stack from elfutils . For example,
$ sudo eu-stack -id -p $$ PID 9189 - process TID 9189: #0 0x00007fd36c69e687 __GI___waitpid #1 0x000055ba004c0c19 #2 0x000055ba004c234b wait_for #3 0x000055ba004b1b64 execute_command_internal #4 0x000055ba004b1bf2 execute_command #5 0x000055ba0049c274 reader_loop #6 0x000055ba0049ac7f main #7 0x00007fd36c5dbb97 __libc_start_main #8 0x000055ba0049b54a _start
One can write one-liners for more complex stuff. For example, to list all thread stacks for the Google Chrome (which is running multiple processes and threads!) one can do
sudo true pidof chrome | sudo xargs -rn1 timeout 1s eu-stack -id -p
The timeout is used to prevent stalling on processes in uninterruptible sleep (some more recent kernel versions may allow getting stacks for those processes, too). Set timeout longer if you’re willing to wait longer to get the stack.
And if you have a busy system where only some of the threads or processes are locked, one can take a snapshot of current process states like this
sudo true pidof apache2 | sort -n | sudo xargs -rn1 timeout 1s eu-stack -id -p > snap1 sleep 10s pidof apache2 | sort -n | sudo xargs -rn1 timeout 1s eu-stack -id -p > snap2 diff -u100 --color snap1 snap2
and you can identify stacks that did not change during 10 seconds (the sort is needed to make the stack order stable so you can meaningfully compare the outputs). If you get an errors such as
eu-stack: dwfl_linux_proc_report pid 25062: No such file or directory eu-stack: dwfl_linux_proc_report pid 25068: Exec format error
it just means that the process 25062 exited after pidof listed it but before eu-stack had queried its state, and process 25068 was tearing down at the same time the stack trace was being built and as a result the stack building failed while reading the executable pointed via proc filesystem.