Saya memiliki proses di Linux yang mendapatkan kesalahan segmentasi. Bagaimana saya bisa mengatakannya untuk menghasilkan dump inti ketika gagal?
Saya memiliki proses di Linux yang mendapatkan kesalahan segmentasi. Bagaimana saya bisa mengatakannya untuk menghasilkan dump inti ketika gagal?
Jawaban:
Ini tergantung pada shell apa yang Anda gunakan. Jika Anda menggunakan bash, maka perintah ulimit mengontrol beberapa pengaturan yang berkaitan dengan eksekusi program, seperti apakah Anda harus membuang inti. Jika Anda mengetik
ulimit -c unlimited
maka itu akan memberi tahu bash bahwa programnya dapat membuang inti dari berbagai ukuran. Anda dapat menentukan ukuran seperti 52M daripada yang tidak terbatas jika Anda mau, tetapi dalam praktiknya ini tidak perlu karena ukuran file inti mungkin tidak akan pernah menjadi masalah bagi Anda.
Di tcsh, Anda akan mengetik
limit coredumpsize unlimited
Seperti dijelaskan di atas, pertanyaan sebenarnya yang diajukan di sini adalah bagaimana mengaktifkan dump inti pada sistem di mana mereka tidak diaktifkan. Pertanyaan itu terjawab di sini.
Jika Anda datang ke sini berharap belajar cara menghasilkan dump inti untuk proses yang digantung, jawabannya adalah
gcore <pid>
jika gcore tidak tersedia di sistem Anda maka
kill -ABRT <pid>
Jangan gunakan kill -SEGV karena itu akan sering memanggil penangan sinyal sehingga lebih sulit untuk mendiagnosis proses macet
-ABRT
akan memanggil penangan sinyal daripada -SEGV
, karena pembatalan lebih mungkin dipulihkan daripada segfault. (Jika Anda menangani segfault, biasanya itu hanya akan memicu lagi begitu pawang Anda keluar.) Pilihan sinyal yang lebih baik untuk menghasilkan dump inti adalah -QUIT
.
Untuk memeriksa di mana core dump dihasilkan, jalankan:
sysctl kernel.core_pattern
atau:
cat /proc/sys/kernel/core_pattern
di mana %e
nama proses dan %t
waktu sistem. Anda dapat mengubahnya /etc/sysctl.conf
dan memuat ulang oleh sysctl -p
.
Jika file inti tidak dihasilkan (uji dengan: sleep 10 &
dan killall -SIGSEGV sleep
), periksa batas oleh: ulimit -a
.
Jika ukuran file inti Anda terbatas, jalankan:
ulimit -c unlimited
untuk membuatnya tidak terbatas.
Kemudian uji lagi, jika core dumping berhasil, Anda akan melihat "(core dumped)" setelah indikasi kesalahan segmentasi seperti di bawah ini:
Kesalahan segmentasi: 11 (core dumped)
Lihat juga: core dumped - tetapi file inti tidak ada di direktori saat ini?
Di Ubuntu, dump inti ditangani oleh Apport dan dapat ditemukan di /var/crash/
. Namun, ini dinonaktifkan secara default di rilis stabil.
Untuk detail lebih lanjut, silakan periksa: Di mana saya menemukan dump inti di Ubuntu? .
Untuk macOS, lihat: Bagaimana cara menghasilkan core dumps di Mac OS X?
Apa yang saya lakukan pada akhirnya adalah melampirkan gdb ke proses sebelum crash, dan kemudian ketika mendapat segfault saya menjalankan generate-core-file
perintah. Itu memaksa generasi dump inti.
ge
)
ulimit -c
untuk unlimited
, tetapi file inti masih tidak dibuat, generate-core-file
file dalam sesi gdb membuat file inti, terima kasih.
Mungkin Anda bisa melakukannya dengan cara ini, program ini adalah demonstrasi cara menjebak kesalahan segmentasi dan shell ke debugger (ini adalah kode asli yang digunakan di bawah AIX
) dan mencetak jejak stack hingga ke titik kesalahan segmentasi. Anda perlu mengubah sprintf
variabel yang akan digunakan gdb
dalam kasus Linux.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);
struct sigaction sigact;
char *progname;
int main(int argc, char **argv) {
char *s;
progname = *(argv);
atexit(cleanup);
init_signals();
printf("About to seg fault by assigning zero to *s\n");
*s = 0;
sigemptyset(&sigact.sa_mask);
return 0;
}
void init_signals(void) {
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGSEGV);
sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGBUS);
sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGQUIT);
sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGHUP);
sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGKILL);
sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}
static void signal_handler(int sig) {
if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
if (sig == SIGSEGV || sig == SIGBUS){
dumpstack();
panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
}
if (sig == SIGQUIT) panic("QUIT signal ended program\n");
if (sig == SIGKILL) panic("KILL signal ended program\n");
if (sig == SIGINT) ;
}
void panic(const char *fmt, ...) {
char buf[50];
va_list argptr;
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
va_end(argptr);
fprintf(stderr, buf);
exit(-1);
}
static void dumpstack(void) {
/* Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];
sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
/* Change the dbx to gdb */
system(dbx);
return;
}
void cleanup(void) {
sigemptyset(&sigact.sa_mask);
/* Do any cleaning up chores here */
}
Anda mungkin harus menambahkan parameter untuk mendapatkan gdb untuk membuang inti seperti yang ditunjukkan di sini di blog ini di sini .
Ada banyak hal yang dapat memengaruhi pembentukan dump inti. Saya menemukan ini:
/proc/sys/kernel/core_pattern
. /proc/sys/fs/suid_dumpable
dapat mencegah core dihasilkan.Ada lebih banyak situasi yang dapat mencegah generasi yang dijelaskan di halaman manual - coba man core
.
Untuk mengaktifkan core dump, lakukan hal berikut:
Dalam /etc/profile
berkomentar, baris:
# ulimit -S -c 0 > /dev/null 2>&1
Dalam /etc/security/limits.conf
komentar di luar garis:
* soft core 0
jalankan cmd limit coredumpsize unlimited
dan periksa dengan cmd limit
:
# limit coredumpsize unlimited
# limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize 10240 kbytes
coredumpsize unlimited
memoryuse unlimited
vmemoryuse unlimited
descriptors 1024
memorylocked 32 kbytes
maxproc 528383
#
untuk memeriksa apakah corefile ditulis, Anda dapat mematikan proses yang berkaitan dengan cmd kill -s SEGV <PID>
(tidak diperlukan, kalau-kalau tidak ada file inti yang ditulis, ini dapat digunakan sebagai cek):
# kill -s SEGV <PID>
Setelah corefile telah ditulis pastikan untuk menonaktifkan pengaturan coredump lagi di file terkait (1./2./3.)!
Untuk Ubuntu 14.04
Periksa dump inti diaktifkan:
ulimit -a
Salah satu garis harus:
core file size (blocks, -c) unlimited
Jika tidak :
gedit ~/.bashrc
dan tambahkan ulimit -c unlimited
ke akhir file dan simpan, jalankan kembali terminal.
Bangun aplikasi Anda dengan informasi debug:
Di Makefile -O0 -g
Jalankan aplikasi yang membuat dump inti (file dump inti dengan nama 'core' harus dibuat di dekat file application_name):
./application_name
Jalankan di bawah gdb:
gdb application_name core
ulimit -c unlimited
terminal untuk solusi sementara, karena hanya mengedit yang ~/.bashrc
memerlukan terminal restart untuk perubahan membuat efek.
Secara default Anda akan mendapatkan file inti. Periksa untuk melihat bahwa direktori saat ini dari proses dapat ditulisi, atau tidak ada file inti yang akan dibuat.
Lebih baik menyalakan core dump secara terprogram menggunakan system call setrlimit
.
contoh:
#include <sys/resource.h>
bool enable_core_dump(){
struct rlimit corelim;
corelim.rlim_cur = RLIM_INFINITY;
corelim.rlim_max = RLIM_INFINITY;
return (0 == setrlimit(RLIMIT_CORE, &corelim));
}
ulimit -c unlimited
di lingkungan baris perintah, dan kemudian jalankan kembali aplikasi.
ulimit -c unlimited
. Anda juga dapat mengkompilasi dengan definisi marco, aplikasi tidak akan menyertakan enable_core_dump
simbol jika tidak mendefinisikan makro saat rilis, dan Anda akan mendapatkan penggantian dump inti dengan versi debug.
Perlu disebutkan bahwa jika Anda memiliki set sistemd , maka hal-hal sedikit berbeda. Pengaturan biasanya akan memiliki file inti yang akan disalurkan, melalui core_pattern
nilai sysctl, melalui systemd-coredump(8)
. Ukuran file inti rlimit biasanya akan dikonfigurasikan sebagai "tidak terbatas".
Maka dimungkinkan untuk mengambil dump inti dengan menggunakan coredumpctl(1)
.
Penyimpanan dump inti, dll. Dikonfigurasi oleh coredump.conf(5)
. Ada beberapa contoh cara mendapatkan file inti di halaman manual coredumpctl, tetapi singkatnya, akan terlihat seperti ini:
Temukan file inti:
[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET 16163 1224 1224 11 present /home/vps/test_me
Dapatkan file inti:
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
Semua jawaban lain sendiri tidak membantu saya. Tapi jumlah berikut berhasil
Buat ~/.config/apport/settings
dengan konten berikut:
[main]
unpackaged=true
(Ini memberitahu apport juga untuk menulis dump inti untuk aplikasi khusus)
periksa: ulimit -c
. Jika output 0, perbaiki dengan
ulimit -c unlimited
Hanya untuk dalam kasus restart apport:
sudo systemctl restart apport
File kerusakan sekarang ditulis dalam bahasa /var/crash/
. Tetapi Anda tidak dapat menggunakannya dengan gdb. Untuk menggunakannya dengan gdb, gunakan
apport-unpack <location_of_report> <target_directory>
Informasi lebih lanjut:
core_pattern
. Ketahuilah, bahwa file itu mungkin akan ditimpa oleh layanan yang sesuai saat memulai ulang.ulimit -c
nilai mungkin akan berubah secara otomatis saat Anda sedang mencoba jawaban lain dari web. Pastikan untuk memeriksanya secara teratur selama pengaturan pembuatan inti sampah Anda.Referensi: