How to detect file descriptor leaks in Node - node.js

I suspect that I have a file descriptor leak in my Node application, but I'm not sure how to confirm this. Is there a simple way to detect file descriptor leaks in Node?

Track open files
On linux you can use the lsof command to list the open files [for a process].
Get the PIDs of the thing you want to track:
ps aux | grep node
Let's say its PID 1111 and 1234, list the open files:
lsof -p 1111,1234
You can save that list and compare when you expect them to be released by your app.
Make it easier to reproduce
If it's taking a while to confirm this (because it takes a while to run out of descriptors) you can try to lower the limit for file descriptors available using ulimit
ulimit -n 500 #or whatever number makes sense for you
#now start your node app in this terminal

Related

RHEL Linux: Discover what processes are using a specific disk

I need to discover what processes are using a specific disk. This is a multipath disk but I cannot find a way of setting up a way to record to a log file what processes are running when a particular disk is being read or written to. I know the major:minor block IDs using lsblk then lsof but these only show current activity and as there currently is none, I cannot find out the process that uses this disk.
Any ideas anyone?
You can use lsof. Lsof revision lists on its standard output file information about files opened by processes. for example this command below will list all files that are opened for writing:
lsof | grep -e "[[:digit:]]\+w > mylogfile.log"
you can redirect the command to log file if you which with the redirect operator >

Linux File descriptors

I have a Java program after 2 weeks of running in average will become stuck and produce the following error:
Caused by: java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:415)
at sun.nio.ch.Net.socket(Net.java:408)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:105)
That hints to me that many sockets are opened but never closed.
Before diving into programmatic instrumentation i started to inspect what information i could draw from linux itself. I am using Redhat.
And then, a few questions came up as follows:
Why the following commands do not give the same output?
See
[ec2-user#ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
592
[ec2-user#ip-172-22-28-102 ~]$ sudo lsof -a -p 32085 | wc -l
655
Is there a way to know from the proc stat info which thread created which file descriptor?
It seems like there is not because if i do the following, i am getting the same information:
[ec2-user#ip-172-22-28-102 ~]$ sudo ls /proc/32085/task/22386/fd | wc -l
592
[ec2-user#ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
592
Same if i go to the thread directly from under /proc/ .
Thx
Is there a way to know from the proc stat info which thread created which file descriptor?
I am pretty sure the answer here is "no". File descriptors are opened by processes, not threads (and will be visible to all threads spawned by the same process).
Why the following commands do not give the same output?
First, the -a argument to lsof appears to be a no-op in this case. Specfically, the man says that it "causes list selection options to be ANDed, as described above". So you are really just running:
sudo lsof -p 32085
And that will print things other than open file descriptors (such as memory-mapped files, current working directory, etc), while /proc/<PID>/fd contains only open file descriptors. So you're getting different results because you're asking for different information.
The only reason you can receive that message is that you have opened files and you didn't close them after use. You have a file descriptor leak in your java application. Java programmers normally don't check memory as the garbage collector copes with unreferenced objects. If you save file descriptors without closing in some data structure or you don't close the files after using, you can reach the maximum limit allowed to a process (this is controlled per process and can be changed by the ulimit shell command)
But if your problem is a file descriptor leak, pushing up the ulimit will only delay the problem some time. File descriptors must be closed, or you'll run into trouble.
I've just ran across this difference today, the explanation is that lsof takes into account more types of files, like memory-mapped objects, run-time libraries etc

How to close open (deleted) file descriptor on linux shell

If i use
lsof -n | grep deleted
I have along list of php5-fpm list values.
two sample output of a list value:
(deleted)/dev/zero (stat: No such file or directory)
(deleted)/tmp/.ZendSem.JQTejx
1) How can i close them within an openVZ container?
2) Is this a result of forgetting to close a mysql handle within a php script?
df -h
shows 41% /var/lib/vz/root/102/var/www/clients/client1/web1/log
and within the log directory there are only a few MB
so how to restore the lost webspace??

tail -f always displays "Killed"

When doing
tail -f /var/log/apache2/access.log
It shows logs and then
Killed
I have to re-execute tail -f to see new logs.
How do I make tail -f continually display logs without killing itself?
The first thing I'd do is try --follow instead of -f. Your problem could be happening because your log file is being rotated out. From the man page:
With --follow (-f), tail defaults to following the file descriptor, which means that even if a tail'ed file is renamed, tail will continue to track its end. This default behavior is not desirable when you really want to track the actual name of the file, not the file descriptor (e.g., log rotation). Use --follow=name in that case. That causes tail to track the named file in a way that accommodates renaming, removal and creation.*
tail -f should not get killed.
Btw, tail does not kill itself, it is killed by something. For example system is out of memory or resource limit is too restrictive.
Please figure out what kills your tail, using for example gdb or strace. Also check your environment, at least ulimit -a and dmesg for any clues.
If your description is correct, and tail actually displays
Killed
then it is probably not happening as a result of log rotation. Log rotation will causes tail to stop displaying new lines, but even if the file is deleted, tail will not be killed.
Rather, some other process on the system, or perhaps the kernel, is sending it a signal 9 (SIGKILL). Possible causes for this include:
A user in another terminal issuing a command such as kill -9 1234 or pkill -9 tail
Some other tool or daemon (although I can't think of any that would do this)
The kernel itself can send SIGKILL to your process. One scenario under which it would do this is if the OOM (Out of memory) killer kicked in. This happens when all RAM and swap in the system is used. The kernel will select a process which is using a lot of memory and kill it. If this was happening it would be visible in syslog, but it is quite unlikely that tail would use that much memory.
The kernel can send you SIGKILL if RLIMIT_CPU (the limit on the amount of CPU time your process has used) is exceeded. If you leave tail running for long enough, and you have a ulimit set, then this can happen. To check for this (and other resource limitations) use ulimit -a
In my opinion, either the first or last of these explanations seems most likely.
You need to use tail -F logfile , it will not get terminate if log file rotate.

How do I find out what process has a lock on a file in Linux?

Today I had the problem that I couldn't delete a folder because "it was busy".
How can I find out which application to blame for that or can I just delete it with brute force?
Use lsof to find out what has what files are open.
man lsof or have a look here
The fuser Unix command will give you the PIDs of the processes accessing a file.
lslocks lists information about all the currently held file locks in a Linux system. (part of util-linux) this utility has support for json output, which is nice for scripts.
~$ sudo lslocks
COMMAND PID TYPE SIZE MODE M START END PATH
cron 873 FLOCK 4B WRITE 0 0 0 /run/crond.pid
..
..
fuser will show you which processes are accessing a file or directory.

Resources