Technical Blog Post
Abstract
PROBEVUE: DETECT FILE DESCRIPTORS LEAK
Body
This small script will keep a list of file descriptors obtained by calls like 'open()',
accept(), socket() and store them in an associative array. When a given fd is closed
it will be marked 'closed' in the array. Every few seconds (1h by default) the script will output the list
of file descriptors in use by the process. Note that IOCP (IO Completion Port) related
file descriptors are not handled as probevue doesn't have access to those calls.
Some examples of output:
-- open_files array (pid 11403730) [END PROBE]:
key value
0 unused
6 notype - closed
7 notype - closed
8 /home/dalla/sqllib/db2dump/db2diag.log - closed - closed
9 /home/dalla/sqllib/db2dump/db2diag.log - closed
10 /home/dalla/sqllib/msg/en_US.iso88591/db2diag.mo - closed
11 /etc/vfs - closed
12 /home/dalla/dalla/NODE0000/SQL00001/SQLDBCONF - closed
13 /home/dalla/dalla/NODE0000/SQL00001/SQLOGCTL.GLFH.2 - closed
14 /home/dalla/dalla/NODE0000/SQL00001/LOGSTREAM0000/S0000001.LOG - closed
15 /home/dalla/dalla/NODE0000/SQL00001/LOGSTREAM0000/S0000002.LOG - closed
16 /home/dalla/dalla/NODE0000/SQL00001/SQLOGCTL.GLFH.2 - closed
17 /home/dalla/dalla/NODE0000/SQL00001/SQLDBCONF - closed - closed
As can be seen in the list each file descriptor (key) has a name or 'type'
associated with it and a flag indicating whether it's closed or not.
-- open_files array (pid 58720996):
key value
0 unused
3 socket()
4 accept()
-- open_files array (pid 58720996) [END PROBE]:
key value
0 unused
3 socket()
4 accept()
In this case, a server with 2 sockets opened. One for listening and the other
dedicated to an incoming connection.
The script is here:
/*
* fdleak1.pb: Track files opened but not closed for a given process.
*
* Run as user 'root' using the following command line:
*
* probevue -s 32 -o fdleak1.out fdleak1.pb <pid>
*
*
* dalla
*/
int open(char *);
int close(int);
int socket();
int accept();
__thread int in_open;
__thread char *open_path;
int target;
@@BEGIN
{
target = $1;
if (target == 0) {
printf("Usage: probevue -s 32 -o fdleak1.out fdleak1.pb <pid>\n");
exit();
}
open_files[0] = "unused";
}
@@syscall:*:open:entry
when (__pid == target)
{
thread:in_open = 1;
thread:open_path = __arg1;
}
@@syscall:*:open:exit
when ((thread:in_open == 1) && (__rv >= 0))
{
__auto String fname[256];
fname = get_userstring((void *) thread:open_path, -1);
open_files[__rv] = fname;
thread:in_open = 0;
}
@@syscall:*:close:entry
when ((__pid == target) && (__arg1 >= 0))
{
__auto String type[256];
if (exists(open_files, __arg1)) {
type = open_files[__arg1];
open_files[__arg1] = type + " - closed";
} else {
open_files[__arg1] = "notype - closed";
}
}
@@syscall:*:accept:exit
when ((__pid == target) && (__rv >= 0))
{
open_files[__rv] = "accept()";
}
@@syscall:*:socket:exit
when ((__pid == target) && (__rv >= 0))
{
open_files[__rv] = "socket()";
}
@@interval:*:clock:3600000
{
printf("-- open_files array (pid %d):\n", target);
print(open_files, 0, 0);
printf("\n");
}
@@END
{
printf("-- open_files array (pid %d) [END PROBE]:\n", target);
print(open_files, 0, 0);
printf("\n");
exit();
}
UID
ibm13285837