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
-ABRTakan 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 %enama proses dan %twaktu sistem. Anda dapat mengubahnya /etc/sysctl.confdan 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-fileperintah. Itu memaksa generasi dump inti.
ge)
ulimit -cuntuk unlimited, tetapi file inti masih tidak dibuat, generate-core-filefile 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 sprintfvariabel yang akan digunakan gdbdalam 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_dumpabledapat 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/profileberkomentar, baris:
# ulimit -S -c 0 > /dev/null 2>&1Dalam /etc/security/limits.confkomentar di luar garis:
* soft core 0jalankan cmd limit coredumpsize unlimiteddan 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 -aSalah satu garis harus:
core file size (blocks, -c) unlimitedJika tidak :
gedit ~/.bashrcdan tambahkan ulimit -c unlimitedke 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_nameJalankan di bawah gdb:
gdb application_name coreulimit -c unlimitedterminal untuk solusi sementara, karena hanya mengedit yang ~/.bashrcmemerlukan 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 unlimiteddi lingkungan baris perintah, dan kemudian jalankan kembali aplikasi.
ulimit -c unlimited. Anda juga dapat mengkompilasi dengan definisi marco, aplikasi tidak akan menyertakan enable_core_dumpsimbol 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_patternnilai 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/settingsdengan 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 -cnilai 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: