Release UDP port used by dead process on OS X - macos

I am on OS X 10.11.6 and trying to run a program that normally listens on UDP port 8008 upon startup.
This program normally also spawns a couple of helper child processes during its operation, but the port is bound by the parent process.
Unfortunately when exiting the program, sometimes the port remains open, even though the program (parent + children) no longer exist.
When this happens, if I try to run the program again it naturally fails with a EADDRINUSE error, and in these cases no matter what I try, the only solution I found was to reboot the machine.
I'm having a hard time believing that I cannot release the port without a reboot.
Here are some diagnostics that I ran so far (I ran all of these with and without sudo):
Find the process using port 8008 with lsof:
$ lsof -i -n -P | grep UDP | grep 8008
But surprisingly doesn't return any results.
However, I had more luck with netstat:
$ netstat -tulnvp udp | grep 8008
udp4 0 0 *.8008 *.* 196724 9216 47205 0
So, the port is indeed bound, and the culprit is pid 47205, however:
$ ps aux | grep 47205
Doesn't return anything. The same thing for PIDs 47206 and 47207 (most certainly the PIDs assigned to the children). I also tried other variations of the grep (program name, path, etc).
I also looked for any process reporting 47205 as its parent:
$ ps -axo pid,ppid,command | grep 47205
So the children processes are also clearly dead.
Not being able to kill anything, I tried to SIGHUP launchd in the hope that it might remove any zombie child processes:
$ sudo kill HUP 1
$ sudo kill -s HUP 1
But alas, netstat still shows the port bound.
Lastly, I tried to restart the loopback interface:
$ sudo ifconfig lo down
$ sudo ifconfig lo up
But again, to no effect.
I have waited several hours since the program last ran, so I'm pretty sure any timeout would have happened by now, but the port just won't get released.
Any ideas on how to force release the port without a reboot?
Edit:
The program in question is the electron-wrapped Patchwork.
This question originates from this github issue.
Although finding a solution/bugfix that prevents the issue from ocurring in the first place would be ideal, I'm also interested in ways to manually close that port from the terminal

In your code, after you create the socket, but before the bind call, invoke the following:
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
Then call bind. The above will allow the socket bind to succeed even if the port is in use.
Two processes, attempting a recvfrom on the same port, will result in one of the processes receiving the packet, but not the other. And it's not deterministic which one will. So make sure you don't actually have two processes legitimately running and sharing the port.

one related question: mac changed the Behavior of SO_REUSEADDR and SO_REUSEPORT:
Behavior of SO_REUSEADDR and SO_REUSEPORT changed?
and I am the maintainer of iptux[1], if I use SO_REUSEPORT, the program can start, but I can't receive msg from this port, all the message go to unclosed port as a black hole.
[1] https://github.com/iptux-src/iptux

It is indeed possible to close the port manually w/o restarting the machine. On various linux flavors this is usually done w/ GDB by issuing syscalls masquerading as a the process (for example close(fd) syscall on the sockets file descriptor).
The process for that:
Open a UDP port: netcat -u 127.0.0.1 33333.
Check the UDP port: netstat -npu (u for UDP), which will give you the PID that occupies that port.
Run: lsof -np $pid for that PID to get the filedescriptor for the socket.
Then run GDB for that PID: sudo gdb -p 73599
When inside GDB run call close(file_descriptor)
Example:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
netcat 73599 ubunt cwd DIR 259,2 4096 13895497 /home/ubunt/Downloads
netcat 73599 ubunt rtd DIR 259,2 4096 2 /
netcat 73599 ubunt txt REG 259,2 31248 28835938 /bin/nc.openbsd
netcat 73599 ubunt mem REG 259,2 47600 23990813 /lib/x86_64-linux-gnu/libnss_files-2.23.so
netcat 73599 ubunt mem REG 259,2 1868984 23990714 /lib/x86_64-linux-gnu/libc-2.23.so
netcat 73599 ubunt mem REG 259,2 101200 23990866 /lib/x86_64-linux-gnu/libresolv-2.23.so
netcat 73599 ubunt mem REG 259,2 81040 23990710 /lib/x86_64-linux-gnu/libbsd.so.0.8.2
netcat 73599 ubunt mem REG 259,2 162632 23990686 /lib/x86_64-linux-gnu/ld-2.23.so
netcat 73599 ubunt 0u CHR 136,19 0t0 22 /dev/pts/19
netcat 73599 ubunt 1u CHR 136,19 0t0 22 /dev/pts/19
netcat 73599 ubunt 2u CHR 136,19 0t0 22 /dev/pts/19
netcat 73599 ubunt 3u IPv4 22142418 0t0 UDP 127.0.0.1:45255->127.0.0.1:33333
Then GDB:
$sudo gdb -p 73599
...
(gdb) call close(3u)
$1 = 0
You will see that the port is no longer there:
ubunt#ubunt-MS-7A94:~$ lsof -np 73599
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
netcat 73599 ubunt cwd DIR 259,2 4096 13895497 /home/ubunt/Downloads
netcat 73599 ubunt rtd DIR 259,2 4096 2 /
netcat 73599 ubunt txt REG 259,2 31248 28835938 /bin/nc.openbsd
netcat 73599 ubunt mem REG 259,2 47600 23990813 /lib/x86_64-linux-gnu/libnss_files-2.23.so
netcat 73599 ubunt mem REG 259,2 1868984 23990714 /lib/x86_64-linux-gnu/libc-2.23.so
netcat 73599 ubunt mem REG 259,2 101200 23990866 /lib/x86_64-linux-gnu/libresolv-2.23.so
netcat 73599 ubunt mem REG 259,2 81040 23990710 /lib/x86_64-linux-gnu/libbsd.so.0.8.2
netcat 73599 ubunt mem REG 259,2 162632 23990686 /lib/x86_64-linux-gnu/ld-2.23.so
netcat 73599 ubunt 0u CHR 136,19 0t0 22 /dev/pts/19
netcat 73599 ubunt 1u CHR 136,19 0t0 22 /dev/pts/19
netcat 73599 ubunt 2u CHR 136,19 0t0 22 /dev/pts/19
GDB is available for MacOS, so it should work for your case as well.

System may keep socket open till I/O process still in progress. Even when the process died but not explicitly closed the socket. If your socket not closed at hours most probably you're missing something. Try to use low-level kernel investigation instead of top-level utilites like netstat or lsof.
Disclaimer
I'm not OS X expert, and most commands for linux. I still leave it there if someone else will have same problem.
1. Try to see if socket still alive (optional)
I may suggest to check socket communication.
tcpdump -A -s0 port 8080 and tcpdump -A -s0 -ilo port 8080
If you see any data transfered over socket you can be sure the process active. Or may be one of its childs. Later you can catch the pid with strace
2. Check the process and its status
Linux have wonderful procfs. You can get so many things from there. And sure you can see all opened file descriptors
ls -al /proc/47205/fd
If you see output and /proc/47205 exists the pid not released nevertheless ps shows. You will see all opened files and its fds.It looks like
133 -> socket:[32242509]
Where 133 is a fd number
Unfortunately OS X don't have /proc filesystem. The alternative command I found.
procexp 47205 fds
But I'm not sure its 100% working.
3. Closing the file descriptor (socket) in another process
In linux there is nice command
fuser -k -n udp 8080
This will explicitly close all processes blocking port. It seems OS X may have fuser too
Another real hackers way is to connect to process with gdb and run commands inside the process, because file descriptor numbers valid only with in process environment,exactly as #Mindaugas Bernatavičius wrote:
gdb -p 47205
>call shutdown([fd_number],2)
>call close([fd_number])
There is third way, when possible you can just restart whole network. Plese note, down and up just loopback interface is not enough. In linux run
systemctl restart network
4.What to do to prevent socket stuck in system
You should always ensure socked closed before your program exits. I seen many issues with nodejs that sockets stays opened. Calling Socket.destroy() will solve the problem
May be put your socket destroy code here, before exiting the app:
app.on('close', function (code) {
// User closed the app. Kill the host process.
process.exit();
});

Your question look similar to :
release-renew-ip-address-via-terminal-in-os-x
How to reset network stack
Reset TCP/IP is OSX
As you said:
Lastly, I tried to restart the loopback interface:
$ sudo ifconfig lo down
$ sudo ifconfig lo up
Did you try to retart all avaible network interfaces (lan or wlan) and not only the loopback) ?
Instead of ifconfig you may use also native MacOS command utility (from here) to power off then power on the device itself (adapt en0 to your device name):
networksetup -setairportpower en0 off
networksetup -setairportpower en0 on
You may also finally try to release and renew DHCP with:
sudo dhclient -v -r
Regards

Related

M1 mac process keeps autogenerating and locks my port

I tried to run my express app with port 5000, and I found that some processes are already using it:
↳ lsof -i :5000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ControlCe 1677 user 32u IPv4 0x728ff8e52d51c6dd 0t0 TCP *:commplex-main (LISTEN)
ControlCe 1677 user 33u IPv6 0x728ff8e51d98ec65 0t0 TCP *:commplex-main (LISTEN)
So I simply tried to kill them to unlock the port, but it won't work because once I run the kill (or sudo kill) command, the process with the new PID locks my 5000 port again.
↳ kill 1677
↳ lsof -i :5000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ControlCe 2159 user 32u IPv4 0x728ff8e52fd4dc1d 0t0 TCP *:commplex-main (LISTEN)
ControlCe 2159 user 33u IPv6 0x728ff8e51d98d0e5 0t0 TCP *:commplex-main (LISTEN)
I killed the process 1677, and then a new process (with PID 2159) came out.
It has different PID and different Device. I already tried to restart my laptop but it was also not working. Has anyone with M1 or Intel Mac experienced a similar issue like this?
Edit: I think ControlCe means Control Center?
Turning off the AirPlay Receiver (listens on port 5000) fixed the issue for me:
Go to System Preference --> Sharing --> uncheck off the AirPlay Receiver
For more details:
https://utf9k.net/questions/macos-port-5000-monterey/
I had this exact same problem too. I think it's because of macOS Monterey (12.0). To fix it, run this command in a terminal:
pkill ControlCenter; nc -l 5000
...and then hit Ctrl+C a few seconds later.
What that will do, is it will kill the ControlCenter processes, and then it will start an empty netcat TCP server listening on the very port used by ControlCenter, i.e., 5000. That way, because ControlCenter automatically restarts when it's killed, it will allocate that port before ControlCenter starts, so that when it does start, it will find that its port is in use and it will die.

SNMPd opens "random" UDP port besides 161 and 162 to the outside

I would like to use snmp to monitor my localhost and have installed the corresponding package on Ubuntu 18.03 with apt install snmp. Without having changed the default configuration, I have launched the daemon with systemctl start snmpd. After launching the daemon the output of lsof -i -n | grep snmpd is as follows:
snmpd 14668 Debian-snmp 12u IPv4 13252990 0t0 UDP 127.0.0.1:snmp
snmpd 14668 Debian-snmp 13u IPv4 13252988 0t0 UDP *:41898
I am wondering about the second line of the output as the port has been opened to the outside. Restarting the daemon changes the open port to another (randomized?) high port number. I have been looking up this behaviour a couple of hours and wasn´t able to find any explanation.
Can anybody explain to me whats going on here or how to disable/remove the open port?
Configuration
AgentAdress is configured as follows:
# /etc/snmp/snmpd.conf
# Listen for connections from the local system only
agentAddress udp:127.0.0.1:161
The daemon has been launched with following options:
# /etc/default/snmp
# snmpd options (use syslog, close stdin/out/err).
SNMPDOPTS='-Lsd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf -p /run/snmpd.pid'
Output of ps aux | grep snmpd
/usr/sbin/snmpd -Lsd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f
So, if anybody comes across the same question: The UDP port has been opened by snmp-traps. In order to avoid this behavior, I had to comment out following line in the snmpd.conf:
/etc/snmp/snmpd.conf
# ACTIVE MONITORING
# send SNMPv1 traps
# !comment this line out!
# trapsink localhost public
Read this link for further information: https://sourceforge.net/p/net-snmp/mailman/message/29219475/

How to remotely start and stop a service by Port number?

I have a file containing IP addresses and port numbers only. I know how to start a service by its name but how to start and stop it by port number?
for port in $(cat /home/asd/iplog.txt); do
service /etc/init.d/$port | cut -d\: -f2 start
done
here is the iplog.txt output:
192.168.1.2:21
192.168.2.25:80
192.168.5.230:25
and the output of the script:
/etc/init.d/192.168.1.2:21: unrecognized service
cut: start: no such file or directory
/etc/init.d/192.168.2.25:80: unrecognized service
cut: start: no such file or directory
Now I have two questions:
How to start and stop a service by its port number?
how to do it remotely?
as I am not familiar with shell scripting, I really need your help please.
How to find a service's PID/command by its port number?
You can kill it/them to stop the service. But this is not the best way.
#lsof-i :22
Command PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 14543 root 3u IPv4 4132251 0t0 TCP *:ssh (LISTEN)
sshd 14543 root 4u IPv6 4132253 0t0 TCP *:ssh (LISTEN)
#ps 14543
PID TTY STAT TIME COMMAND
14543 ? Ss 0:00 /usr/sbin/sshd
how to do it remotely?
ssh user#remote 'your command to stop service'

Can't package react native because of port 8081 sunproxyadmin

when I run this in terminal:
lsof -n -i4TCP:8081
I get this
node 10901 me 28u IPv6 0xbcad49 0t0 TCP *:sunproxyadmin (LISTEN)
foo 11957 me 15u IPv4 0xbcad49 0t0 TCP 127.0.0.1:61127->127.0.0.1:sunproxyadmin (CLOSE_WAIT)
What is this sunproxyadmin?
Per http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=8081, TCP port 8081 is the well known port for sunproxyadmin the same way 80 is the well known port for http. In this case, you have a node process that is listening on port 8081, but lsof is trying to be helpful and show the well known port for this. Under linux, this is defined in /etc/services; I would expect OS X is similar.
Edit 1: Note that per Apple Man Pages, passing -P
inhibits the conversion of port numbers to port names for network files.
Inhibiting the conversion may make lsof run a little faster. It
is also useful when port name lookup is not working properly.
This should cause lsof to not print out the confusing sunproxyadmin for something that just happens to use the port that Sun registered.
Edit 2: The second column in your response (e.g. 10901 in the first row, which is the one you want, and 11957 in the second row) should be the process ID. If you do ps aux | grep 10901 (or ps elf | grep [pid], as I can't remember which works right for OSX and don't have it handy) you should get something like:
apache 19783 0.0 0.2 251888 8580 ? S Oct07 0:00
/usr/sbin/httpd -DFOREGROUND
(or to make something up:
nodeuser 10901 0.0 0.2 251888 8580 ? S Oct07 0:00 node index.js
)
You can kill it with kill -9 10901 (or whatever the PID was) though you might find it comes back if it's running as a service or what.
This is useful enough to add to your bash profile:
function findbyport()
{
sudo lsof -P -iTCP:$1 -sTCP:LISTEN
}
Kill it, do in your terminal
sudo lsof -i :8081
from there get the PID number and then run
kill -9 <PID NUMBER>
You can check on FB documentation for more info
If you don't want to kill sunproxyadmin process, let try to start React native in different port with command:
react-native start --port your_port
Then open Dev settings (see how to open dev menu), and modify Debug server host & port for device to: your_local_ip:your_port
There is this MACAFEE antivirus running on my Mac. I am able to kill it(Even though I should not be killing it, I tried it, and looks like it never dies! Sudo has no power after all!).So after a lot of research I have tried this one.
Step 1 : Get the process' PID
sudo lsof -n -i4TCP:8081
Step 2 : Find the launchd endpoint
sudo launchctl list | grep
Step 3 : Remove mcafee
sudo launchctl remove com.mcafee.agent.macmn
If this one works for you pls say thanks to me and as well as https://fantashit.com/unable-to-perform-react-native-start/

Why does OS X allow listening on the same TCP port twice?

I was trying to debug port allocation problems in Jenkins on OS X by listening to certain ports with netcat, which led to some weird results.
In a terminal on OS X 10.8.2:
$ uname -rs
Darwin 12.2.1
$ nc -l 54321
Then in an second terminal:
$ nc -l 54321
And in a third terminal, lsof shows that both instances have bound to the same port:
$ lsof -i | grep 54321
nc 70706 chris 3u IPv4 0x55618c024692f4d1 0t0 TCP *:54321 (LISTEN)
nc 70769 chris 3u IPv4 0x55618c0232cb8661 0t0 TCP *:54321 (LISTEN)
On Linux:
First terminal:
$ uname -rs
Linux 3.2.0-34-generic
$ nc -l 54321
Second terminal:
$ nc -l 54321
nc: Address already in use
Why doesn't OS X also report that the address is already in use?
The binary on OS X is setting the SO_REUSEPORT socket option, which allows completely duplicate bindings (setsockopt on OS X). You can verify this using dtrace on OS X.
The netcat binary on Linux does not do this, so you get a bind error as expected. Again, you can verify that using strace. I belive SO_REUSEPORT is deprecated, or not even available on newer Linux kernels.

Resources