--- /dev/null
+from LTTngAnalyzes.common import *
+
+class Statedump():
+ def __init__(self, tids):
+ self.tids = tids
+
+ def merge_fd_dict(self, p, parent):
+ if len(p.fds.keys()) != 0:
+ for fd in p.fds.keys():
+ if fd not in parent.fds.keys():
+ parent.fds[fd] = p.fds[fd]
+ else:
+ # best effort to fix the filename
+ if len(parent.fds[fd].filename) == 0:
+ parent.fds[fd].filename = p.fds[fd].filename
+ # merge the values as they are for the same FD
+ parent.fds[fd].read += p.fds[fd].read
+ parent.fds[fd].write += p.fds[fd].write
+ parent.fds[fd].open += p.fds[fd].open
+ parent.fds[fd].close += p.fds[fd].close
+ p.fds.pop(fd, None)
+ if len(p.closed_fds.keys()) != 0:
+ for fd in p.closed_fds.keys():
+ if fd not in parent.closed_fds.keys():
+ parent.closed_fds[fd] = p.closed_fds[fd]
+ else:
+ # best effort to fix the filename
+ if len(parent.closed_fds[fd].name) == 0:
+ parent.closed_fds[fd].name = p.closed_fds[fd].name
+ # merge the values as they are for the same FD
+ parent.closed_fds[fd].read += p.closed_fds[fd].read
+ parent.closed_fds[fd].write += p.closed_fds[fd].write
+ parent.closed_fds[fd].open += p.closed_fds[fd].open
+ parent.closed_fds[fd].close += p.closed_fds[fd].close
+ p.closed_fds.pop(fd, None)
+
+ def process_state(self, event):
+ tid = event["tid"]
+ pid = event["pid"]
+ name = event["name"]
+ if not tid in self.tids:
+ p = Process()
+ p.tid = tid
+ self.tids[tid] = p
+ else:
+ p = self.tids[tid]
+ # Even if the process got created earlier, some info might be
+ # missing, add it now.
+ p.pid = pid
+ p.comm = name
+
+ if pid != tid:
+ # create the parent
+ if not pid in self.tids:
+ parent = Process()
+ parent.tid = pid
+ parent.pid = pid
+ parent.comm = name
+ self.tids[pid] = parent
+ else:
+ parent = self.tids[pid]
+ # If the thread had opened FDs, they need to be assigned
+ # to the parent.
+ self.merge_fd_dict(p, parent)
+
+ def file_descriptor(self, event):
+ pid = event["pid"]
+ fd = event["fd"]
+ filename = event["filename"]
+
+ if not pid in self.tids:
+ p = Process()
+ p.pid = pid
+ p.tid = pid
+ self.tids[pid] = p
+ else:
+ p = self.tids[pid]
+
+ if not fd in p.fds.keys():
+ newfile = FD()
+ newfile.filename = filename
+ newfile.fd = fd
+ p.fds[fd] = newfile
+ else:
+ # just fix the filename
+ p.fds[fd].filename = filename
self.tids = tids
self.syscalls = syscalls
# list of syscalls that open a FD (in the exit_syscall event)
- self.open_syscalls = ["sys_open", "sys_openat"]
+ self.open_syscalls = ["sys_open", "sys_openat", "sys_accept",
+ "sys_fcntl", "sys_socket", "sys_dup2"]
# list of syscalls that close a FD (in the "fd =" field)
self.close_syscalls = ["sys_close"]
s = t.syscalls[name]
s.count += 1
- def track_open(self, name, event, cpu):
+ def track_open(self, name, proc, event, cpu):
cpu.current_syscall = {}
- cpu.current_syscall["name"] = name
if name in ["sys_open", "sys_openat"]:
cpu.current_syscall["filename"] = event["filename"]
+ elif name in ["sys_accept", "sys_socket"]:
+ cpu.current_syscall["filename"] = "socket"
+ elif name in ["sys_dup2"]:
+ newfd = event["newfd"]
+ oldfd = event["oldfd"]
+ if newfd in proc.fds.keys():
+ self.close_fd(proc, newfd)
+ if oldfd in proc.fds.keys():
+ cpu.current_syscall["filename"] = proc.fds[oldfd].filename
+ else:
+ cpu.current_syscall["filename"] = ""
+ elif name in ["sys_fcntl"]:
+ # F_DUPFD
+ if event["cmd"] != 0:
+ return
+ oldfd = event["fd"]
+ if oldfd in proc.fds.keys():
+ cpu.current_syscall["filename"] = proc.fds[oldfd].filename
+ else:
+ cpu.current_syscall["filename"] = ""
+ cpu.current_syscall["name"] = name
- def track_close(self, name, event, cpu):
- t = self.tids[cpu.current_tid]
- fd = event["fd"]
- if not fd in t.fds.keys():
-# print("%lu : Closing FD %d in %d without open" %
-# (event.timestamp, fd, t.tid))
- return
- filename = t.fds[fd].filename
- if filename in t.closed_fds.keys():
- f = t.closed_fds[filename]
+ def close_fd(self, proc, fd):
+ filename = proc.fds[fd].filename
+ if filename in proc.closed_fds.keys():
+ f = proc.closed_fds[filename]
f.close += 1
- f.read += t.fds[fd].read
- f.write += t.fds[fd].write
+ f.read += proc.fds[fd].read
+ f.write += proc.fds[fd].write
else:
- t.closed_fds[filename] = t.fds[fd]
- t.closed_fds[filename].close = 1
+ proc.closed_fds[filename] = proc.fds[fd]
+ proc.closed_fds[filename].close = 1
# print("Close FD %s in %d (%d, %d, %d, %d)" %
-# (filename, t.tid, t.fds[fd].read, t.fds[fd].write,
-# t.fds[fd].open, t.fds[fd].close))
- t.fds.pop(fd, None)
+# (filename, proc.tid, proc.fds[fd].read, proc.fds[fd].write,
+# proc.fds[fd].open, proc.fds[fd].close))
+ proc.fds.pop(fd, None)
+
+ def track_close(self, name, proc, event, cpu):
+ fd = event["fd"]
+ if not fd in proc.fds.keys():
+ print("%lu : Closing FD %d in %d without open" %
+ (event.timestamp, fd, proc.tid))
+ return
+ self.close_fd(proc, fd)
def track_fds(self, name, event, cpu_id):
# we don't know which process is currently on this CPU
c = self.cpus[cpu_id]
if c.current_tid == -1:
return
+ t = self.tids[c.current_tid]
+ # if it's a thread, we want the parent
+ if t.pid != -1 and t.tid != t.pid:
+ t = self.tids[t.pid]
if name in self.open_syscalls:
- self.track_open(name, event, c)
+ self.track_open(name, t, event, c)
elif name in self.close_syscalls:
- self.track_close(name, event, c)
+ self.track_close(name, t, event, c)
def add_tid_fd(self, event, cpu):
ret = event["ret"]
t = self.tids[cpu.current_tid]
+ # if it's a thread, we want the parent
+ if t.pid != -1 and t.tid != t.pid:
+ t = self.tids[t.pid]
name = cpu.current_syscall["filename"]
if name in t.closed_fds.keys():
fd = t.closed_fds[name]
fd.fd = ret
else:
return
-# if fd.fd in t.fds.keys():
-# print("%lu : FD %d in tid %d was already there, untracked close" %
-# (event.timestamp, fd.fd, t.tid))
+ if fd.fd in t.fds.keys():
+ print("%lu : FD %d in tid %d was already there, untracked close" %
+ (event.timestamp, fd.fd, t.tid))
t.fds[fd.fd] = fd
-# print("%lu : %s opened %s (%d times)" % (event.timestamp, t.comm,
-# fd.filename, fd.open))
+ if t.pid == 21300:
+ print("%lu : %s opened %s (%d times)" % (event.timestamp, t.comm,
+ fd.filename, fd.open))
def entry(self, event):
name = event.name