I have a problem analogous to the one described here:
Prevent fork() from copying sockets
Basically, inside my Lua script I’m spawning another script which:
- doesn’t require communicating with my script either way
- continues running after my script had finished
- is a 3rd party program, code of which I have no control over
The problem is that my Lua script opens a TCP socket to listen on a specific port and after it’s quit and despite an explicit server:close() the child (or more specifically its children) holds onto the socket and keeps the port open (in LISTEN state) preventing my script from running again.
Here’s example code that demonstrates the problem:
require('socket')
print('listening')
s = socket.bind("*", 9999)
s:settimeout(1)
while true do
print('accepting connection')
local c = s:accept()
if c then
c:settimeout(1)
local rec = c:receive()
print('received ' .. rec)
c:close()
if rec == "quit" then break end
if rec == "exec" then
print('running ping in background')
os.execute('sleep 10s &')
break
end
end
end
print('closing server')
s:close()
If I run the above script and echo quit | nc localhost 9999 everything works well – program quits and port is closed.
However if I do echo exec | nc localhost 9999 the program quits but the port is blocked by the spawned sleep (as confirmed by netstat -lpn) until it exits.
How do I tackle this in the simplest possible manner, preferably without adding any extra dependencies.
I found a much simpler solution which utilizes the fact that
os.execute(cmd)runscmdin ashell, which, as it turns out, is capable of closing file descriptors as seen here:http://linux.die.net/man/1/ash (section Redirections )
http://www.gnu.org/software/bash/manual/bashref.html#Redirections
For example (tested in
ash):So in my
luasocketbased example it’s enough to replace:with:
This closes all file descriptors, including my server socket, before executing the actual command (here
sleep 10s) so that it doesn’t hog the port after my script exits. It also has the bonus of taking care ofstdoutandstderrredirection.This is much more compact and uncomplicated than working around
Lua‘s limitations and doesn’t require any extra dependencies. Thanks go to #uclibc where I got some brilliant help with final shell syntax from the embedded linux crew.