UC3M

Grado en Ing. Telemática/Sist. Audiovisuales/Sist. de Comunicaciones

Arquitectura de Sistemas

Septiembre 2017 - Enero 2018

17.2.3. Mal uso de las interfaces POSIX

Otra buena característica de Helgrind es que detecta mal-usos en el API de POSIX. Sigue un ejemplo de cerrojo no debidamente liberado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>       
#include <unistd.h>

pthread_mutex_t mutex_1;

 void *counter_thread(void *ctr)
{   printf("In thread: running...\n");
    pthread_mutex_lock(&mutex_1);
    printf("In thread: Locked printf in thread");
    pthread_mutex_unlock(&mutex_1);
    sleep(1);
    printf("In thread: exiting .............\n");
    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  pthread_t threads[1];
  pthread_mutex_init(&mutex_1, NULL);

  int rc=0;
  printf("(log) In main: creating thread %i\n", 1);
  rc = pthread_create(&threads[0], NULL, counter_thread, NULL);
  if (rc){
      printf("ERROR; return code from pthread_create() is %d\n", rc);
      exit(-1);
     }
  sleep(1);
  
  pthread_mutex_lock(&mutex_1);
  printf("In main: Locked printf in main");
  
  pthread_join(threads[0],NULL);     
  pthread_mutex_destroy(&mutex_1);
  
  return 0;
}
 

Lo cual en Helgrind produce la siguiente salida:

$ gcc -Wall -g -pthread helgrind_threads_api_misuses.c -o helgrind_threads_api_misuses
$ valgrind -v  --tool=helgrind  ./helgrind_threads_api_misuses 

 ==9113== ----------------------------------------------------------------
==9113== 
==9113== Thread #1's call to pthread_mutex_destroy failed
==9113==    with error code 16 (EBUSY: Device or resource busy)
==9113==    at 0x402DFB0: pthread_mutex_destroy (in /usr/lib/valgrind/vgpreload_helgrind-x86-linux.so)
==9113==    by 0x804879D: main (helgrind_threads_api_misuses.c:37)
==9113== 
In main: Locked printf in main==9113== 
==9113== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 41 from 13)
==9113== 
==9113== 1 errors in context 1 of 2:
==9113== ----------------------------------------------------------------
==9113== 
==9113== Thread #1's call to pthread_mutex_destroy failed
==9113==    with error code 16 (EBUSY: Device or resource busy)
==9113==    at 0x402DFB0: pthread_mutex_destroy (in /usr/lib/valgrind/vgpreload_helgrind-x86-linux.so)
==9113==    by 0x804879D: main (helgrind_threads_api_misuses.c:37)
==9113== 
==9113== 
==9113== 1 errors in context 2 of 2:
==9113== ----------------------------------------------------------------
==9113== 
==9113== Thread #1: pthread_mutex_destroy of a locked mutex
==9113==    at 0x402DF3C: pthread_mutex_destroy (in /usr/lib/valgrind/vgpreload_helgrind-x86-linux.so)
==9113==    by 0x804879D: main (helgrind_threads_api_misuses.c:37)
==9113== 
--9113-- 
--9113-- used_suppression:      1 helgrind-glibc2X-005
--9113-- used_suppression:     36 helgrind-glibc2X-004
--9113-- used_suppression:      4 helgrind-glibc2X-101
==9113== 
==9113== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 41 from 13)
 

Se solventa el error añadiendo un unlock en el hilo del main, lo cual quita los dos errores previamente reportados:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Compile with gcc -pdthread
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>       
#include <unistd.h>

pthread_mutex_t mutex_1;

 void *counter_thread(void *ctr)
{   printf("In thread: running...\n");
    pthread_mutex_lock(&mutex_1);
    printf("In thread: Locked printf in thread");
    pthread_mutex_unlock(&mutex_1);
    sleep(1);
    printf("In thread: exiting .............\n");
    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  pthread_t threads[1];
  pthread_mutex_init(&mutex_1, NULL);

  int rc=0;
  printf("(log) In main: creating thread %i\n", 1);
  rc = pthread_create(&threads[0], NULL, counter_thread, NULL);
  if (rc){
      printf("ERROR; return code from pthread_create() is %d\n", rc);
      exit(-1);
     }
  sleep(1);  
  pthread_mutex_lock(&mutex_1);
  printf("In main: Locked printf in main");
  pthread_mutex_unlock(&mutex_1);
  pthread_join(threads[0],NULL);     
  pthread_mutex_destroy(&mutex_1);
  return 0;
}