故事是这样的,有一天客户报了个bug,说我们camera的configuration file坏啦,我们也不知道问题怎么样,只是知道客户那里存在这种问题,怎么办呢,在写configuration file的时候加锁,让它只能一个写,这样我们自以为解了,其实是没找到重现都办法,没法解啊,只能内部加强。
问题重现:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void get_filename_by_fd(int fd)
{
int MAXSIZE = 0xFFF;
char proclnk[0xFFF];
char filename[0xFFF];
ssize_t r;
sprintf(proclnk, "/proc/self/fd/%d", fd);
r = readlink(proclnk, filename, MAXSIZE);
if (r < 0)
{
printf("failed to readlink\n");
return;
}
filename[r] = '\0';
printf("fd -> filename: %d -> %s\n", fd, filename);
}
int main()
{
FILE *fp, *fp_A;
int fno, fno_A;
int ret, ret_A;
// test.txt created earlier
fp = fopen("test.txt", "w+");
if (fp != NULL)
{
fno = fileno(fp);
}
printf("%d: fd=%d\n", __LINE__, fno);
get_filename_by_fd(fno);
ret = close(fno);// extra close
printf("%d: ret=%d\n", __LINE__, ret);
fp_A = fopen("system.txt", "w+");
if (fp_A != NULL)
{
fno_A = fileno(fp_A);
}
printf("%d: fd_A=%d\n", __LINE__, fno_A);
get_filename_by_fd(fno);
ret = fclose(fp); // close the fp
printf("%d: ret=%d\n", __LINE__, ret);
fp = fopen("text.txt", "w+");
if (fp != NULL)
{
fno = fileno(fp);
}
ret_A = fclose(fp_A); // close the fp_A
printf("%d: ret_A=%d\n", __LINE__, ret_A);
fp_A = fopen("system.txt", "w+");
if (fp_A != NULL)
{
fno_A = fileno(fp_A);
}
get_filename_by_fd(fno);
ret= write(fno, "xxxxx", 10);
printf("%d: ret=%d\n", __LINE__, ret);
ret = close(fno); // extra fp
printf("%d: ret=%d\n", __LINE__, ret);
ret = fclose(fp); // cloase the fp
printf("%d: ret=%d\n", __LINE__, ret);
return 0;
}
程序都结果肯定出乎你都意料之外。
weeds@weeds-T68G:~/love/proc$ gcc -o file file.c
weeds@weeds-T68G:~/love/proc$ ./file
35: fd=3
fd -> filename: 3 -> /home/weeds/love/proc/test.txt
38: ret=0
44: fd_A=3
fd -> filename: 3 -> /home/weeds/love/proc/system.txt
47: ret=0
54: ret_A=0
fd -> filename: 3 -> /home/weeds/love/proc/system.txt
62: ret=10
64: ret=0
66: ret=-1
weeds@weeds-T68G:~/love/proc$ cat system.txt
xxxxxweeds@weeds-T68G:~/love/proc$ cat text.txt
weeds@weeds-T68G:~/love/proc$
其实吧,这个很简单,是系统VFS给你申请的文件描述符基本递增的,而当你多写了个close,而恰巧在第二个fclose之前打开啦另外一个文件,那么就会导致你的程序紊乱啦,这种问题异常都难于解决,建议写程序都时候多用心。