c segmentation-fault pthreads core glibc

Engendrar un pthread tiene un cambio drástico en el comportamiento del volcado del núcleo



segmentation-fault pthreads (0)

A continuación se muestra un pequeño programa que utiliza mmap para "asignar" 20 GB de espacio de direcciones virtuales, y luego segfaults. Hay dos comportamientos que se pueden controlar de forma independiente (a través de argumentos de línea cmd): el primero hace que la aplicación realmente escriba en cada uno de los 20 GB; el segundo hace que la aplicación genere un pthread al inicio. Entonces hay 4 formas en que se puede ejecutar el programa.

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <pthread.h> #define DELAY 3 #define THREAD_DELAY 1 #define TIMES 20 #define GB 1024*1024*1024 void* thread_run(void* name){ while(1){ sleep(THREAD_DELAY); } } void thread_start(char* name) { pthread_t thread; int ret; ret = pthread_create(&thread, NULL, thread_run, (void*)name); if(ret){ printf("failure spawing thread [%d]/n", ret); exit(-1); } } int write_to_memory = 0; int start_thread = 0; int main(int argc, char** argv){ int i; void** address_array = malloc(TIMES * sizeof(void*)); int* ptr = (int*)0; printf("PID is %d/n", getpid()); for(i = 0; i < argc; i++){ if(strcmp(argv[i], "write_to_memory") == 0) write_to_memory = 1; if(strcmp(argv[i], "start_thread") == 0) start_thread = 1; } printf("write_to_memory = %d/n", write_to_memory); printf("start_thread = %d/n", start_thread); if(start_thread){ thread_start("OTHER_THREAD"); } sleep(DELAY); for(i = 0; i < TIMES; i++){ address_array[i] = mmap(NULL, GB, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(address_array[i] == MAP_FAILED){ printf("mmap failed"); exit(-2); } } if(write_to_memory){ sleep(DELAY); for(i = 0; i < TIMES; i++){ memset(address_array[i], 0, GB); } } sleep(DELAY); *ptr = 123; return *ptr; }

Al ejecutar el programa de las 4 formas, he visto algo muy extraño: para tres de las cuatro formas en que se puede ejecutar el programa, el volcado del núcleo tendrá un tamaño de ~ 20 GB; sin embargo, si genero un hilo, pero no escribo en la memoria asignada, el volcado del núcleo tiene solo 11 MB de tamaño. No puedo explicar este comportamiento, y me preguntaba si esto se esperaba.

Primero, algunos detalles sobre el medio ambiente:

[user@machine coredump]$ uname -a Linux machine.domain 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux [user@machine coredump]$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) [user@machine coredump]$ /lib/libc.so.6 GNU C Library stable release version 2.12, by Roland McGrath et al. Native POSIX Threads Library by Ulrich Drepper et al

Y ahora la salida

_____________________ PID is 16012 write_to_memory = 0 start_thread = 0 Segmentation fault (core dumped) -rw------- 1 user group 21G Mar 14 22:57 core.16012 _____________________ PID is 16201 write_to_memory = 0 start_thread = 1 Segmentation fault (core dumped) -rw------- 1 user group 11M Mar 14 22:57 core.16201 _____________________ PID is 16234 write_to_memory = 1 start_thread = 0 Segmentation fault (core dumped) -rw------- 1 user group 21G Mar 14 22:58 core.16234 _____________________ PID is 16425 write_to_memory = 1 start_thread = 1 Segmentation fault (core dumped) -rw------- 1 user group 21G Mar 14 22:59 core.16425

¿Es este el comportamiento esperado? Si es así, ¿usar pthreads implica que hay un manejador de segfault por defecto "más inteligente" que se da cuenta de que la memoria asignada no ha sido tocada y por lo tanto no necesita ser volcada?