Как проверить, освобождает ли поток атрибута detached системные ресурсы после выхода?

Я пытаюсь это:

#include<stdio.h>
#include<pthread.h>
void * fun1(void *arg) 
{
  FILE *fp;
  fp=fopen("data","w+");
  if(fp==0)
  {
    perror("fopen");
    return NULL;
  }
  perror("fopen");
  fprintf(fp,"%s\n","file opened");
  return NULL;
}


void main() 
{  
 pthread_attr_t atr;
 pthread_attr_init(&atr);
 pthread_attr_setdetachstate(&atr,PTHREAD_CREATE_DETACHED);

 pthread_t thread1;
 pthread_create(&thread1,&atr,&fun1,NULL);
 pthread_attr_destroy(&atr);
 while(1);
}      

я хочу знать, закроет ли этот поток указатель файла fp автоматически или нет после выхода.


person SoulOfJack    schedule 30.05.2017    source источник
comment
Вы не можете проверить свой код, в конце концов, вы отсоединили поток. Предполагая, что ваш пустой цикл действительно поддерживает процесс, вы можете проверить извне, используя lsof в Linux.   -  person    schedule 30.05.2017
comment
Я сослался на это и согласно описанию, похоже, что файл закрыт на случай отрывной резьбы. Также вы можете использовать этот ссылка для проверки дескриптора открытого файла.   -  person Gaurav Pathak    schedule 30.05.2017
comment
@GauravPathak Обратите внимание, здесь говорится, что ресурсы потока освобождаются при отсоединении и завершении, что отличается от ресурсов, используемых потоком. Нет, файловые дескрипторы не закрываются при завершении потока. Таблица файловых дескрипторов является общим ресурсом внутри процесса, а конкретный fd не принадлежит конкретному потоку.   -  person tofro    schedule 30.05.2017
comment
@FelixPalmen lsof или аналогичный даст вам только дескриптор файла. Если код использует FILE * для доступа к файлу — как в примере — нет простого способа восстановить его, и он может безвозвратно утечь.   -  person Andrew Henle    schedule 30.05.2017
comment
Большое спасибо @tofro   -  person Gaurav Pathak    schedule 30.05.2017


Ответы (3)


я хочу знать, закроет ли этот поток указатель файла fp автоматически или нет после выхода.

Нет, не будет.

Если процесс завершится, указатель файла и базовый дескриптор/дескриптор файла будут закрыты.

Ничего не произойдет с фактическим указателем файла и базовым дескриптором/дескриптором при выходе из потока. Указатель файла останется выделенным со всеми его ресурсами, а базовый дескриптор/дескриптор останется открытым. Если ваш код иначе не отслеживает указатель файла, произойдет утечка.

person Andrew Henle    schedule 30.05.2017
comment
Существует также распространенная, но очень неприятная ловушка, когда поток непреднамеренно закрывает fd дважды — это не повредит в однопоточной среде и будет молча игнорироваться, но с несколькими потоками fd можно было бы легко выделить для другого потока между первым и вторым close() - person tofro; 30.05.2017

Если вы не закроете его, дескриптор файла останется выделенным, и это вызовет утечку памяти, если ваша программа выйдет, не закрыв его. Вы должны явно закрыть его с помощью close(fd). Отсоединение потока просто позволит ему завершиться и высвободить свои собственные ресурсы без необходимости его pthread_join.

person simo-r    schedule 30.05.2017
comment
файловый дескриптор останется выделенным, и это вызовет утечку памяти, если ваша программа выйдет, не закрыв ее ну, любая известная мне недавняя ОС закрывает файловые дескрипторы в момент завершения процесса (не потока). Так они и не текут потом. - person alk; 03.06.2017

Нет, не будет.

Доказательство:

#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<stdbool.h>
#include<unistd.h>

sem_t sem;

void * fun1(void *arg) 
{
    FILE *fp;
    fp=fopen("data","w+");
    if(fp==0)
    {
        perror("fopen");
        return NULL;
    }
    perror("fopen");
    fprintf(fp,"%s\n","file opened");
    sleep(1);
    sem_post(&sem);
    return NULL;
}


int main() 
{  
    pthread_attr_t atr;
    pthread_attr_init(&atr);
    pthread_attr_setdetachstate(&atr,PTHREAD_CREATE_DETACHED);

    sem_init(&sem, 0, 0);

    long pid = getpid();
    char cmd[] = 
        "echo ==================\n"
        "ls /proc/xxxxxx/fd\n"
        "ls /proc/xxxxxx/task\n"
        ;
    sprintf(cmd, 
        "echo ==================\n"
        "ls /proc/%ld/fd\n"
        "ls /proc/%ld/task\n"
        , pid, pid);

    system(cmd);


    pthread_t thread1;
    pthread_create(&thread1,&atr,&fun1,NULL);
    system(cmd);
    pthread_attr_destroy(&atr);

    sem_wait(&sem);
    sleep(1);


    system(
            cmd
          );
    return 0;

}

Возможный вывод:

==================
0
1
2
30697
==================
0
1
2
3
30697
30702
==================
0
1
2
3
30697

Как видите, вновь открытый fd (3) переживает смерть потока (30702). Атрибут detached здесь роли не играет.

person PSkocik    schedule 30.05.2017