How to stop TCP server in Julia? - tcp

TCP example
#async begin
server = listen(2000)
while true
sock = accept(server)
println("Hello World\n")
end
end
To close the connection, you need to call the close method:
close(sock)
How to stop the listener?
close(server) #LoadError: accept: software caused connection abort (ECONNABORTED)

Rather than keep commenting, here's what I think you were probably trying to do:
From the julia REPL:
julia> server = listen(2000)
Base.TCPServer(active)
julia> #async begin
while true
sock = accept(server)
print(readstring(sock))
end
end
From another terminal:
~ $ nc localhost 2000
Hello from the other terminal
[Ctrl-D] % i.e. signal end of file. this closes the connection
In the julia repl, you'll see "Hello from the other terminal" printed as soon as you send the EOF signal, but otherwise the julia prompt will continue as normal. If you repeat this process from the netcat terminal you'll see the message printed in the REPL again, because the socket keeps reactivating inside the while loop.
Ideally if you wanted to shut the whole thing down, you would first close(sock) and then close(server). But, you can't close the socket directly, because it's in the "while" loop and it keeps getting reactivated, and you don't have direct access to the variable "sock".
Therefore you can only close the server, fully expecting an error. So catch it in a try block instead
EDIT: sorry, my bad, the exception relates to the socket, not the server, so you need to wrap that in a try catch block inside your async block instead:
#async begin
while true
try
sock = accept(server)
print(readstring(sock))
catch ex
print("exiting while loop")
break
end
end
end

Related

Airflow operator inside while loop

In Airflow, I have a modified DockerOperator. In the operator args I pass a random port for the port mapping. I choose the port randomly from a interval.
my_task = ModifiedDockerOperator(
...,
port_mapping=_get_random_port_mapping(),
...)
When I run more than one DAG with this operator concurrently, it is possible that I pass to the operator a port equal to the port other running operator is already using. It gives me an error, because you cannot use port mapping with the same host port on two Docker containers at the same time:
docker.errors.APIError: 500 Server Error ... Bind for 0.0.0.0:21099 failed: port is already allocated")
To solve the problem, I would like try starting the task repeatedly until it happens that _get_random_port_mapping() picks a port that is not in use by other running Docker container.
My approach was to place the operator on a while loop, with a try block. Something like this:
is_success = 0
while is_success < 1:
try:
operator = ModifiedDockerOperator(
...,
port_mapping=_get_random_port_mapping(),
...)
is_success += 1
except:
pass
my_task = operator
The "while with try-except" approach had no effect. If the operator tries to run a container with a port that is already in use by other running container, I receive the exact same error that I was receiving before, without the "while with try-except".
Moreover, the "while loop" itself had no effect, as the task immediately fails in the first failed attempt to run the container, and do not try to instantiate the operator a second time.
What am I missing here?

Process and TCPSocket not close properly in crystal

I'm creating a tcp server who accept all the connection and execute incomming data has command line, but when i send "exit" to the tcpsocket, the process and the socket dont close properly
# main.cr
require "socket"
PORT = 2022
def handle_connection(socket)
Process.run("/bin/sh", input: socket, output: socket, error: socket)
end
server = TCPServer.new(PORT)
loop do
if socket = server.accept?
spawn handle_connection(socket)
else
break
end
end
for example, the following code work fine, after sending "exit" to STDIN, the shell is exiting, "process ending" is printedand the program close
channel = Channel(Nil).new
spawn do
Process.run("/bin/sh", input: STDIN, output: STDOUT, error: STDERR)
puts "process ending"
channel.send(nil)
end
channel.receive
for debuggin purpose i have tested this code too but "process ending" was never print until i manually close the tcp socket
# main.cr
require "socket"
PORT = 2022
def handle_connection(socket)
Process.run("/bin/sh", input: socket, output: socket, error: socket)
puts "process ending"
end
server = TCPServer.new(PORT)
loop do
if socket = server.accept?
spawn handle_connection(socket)
else
break
end
end
when i run main.cr, nc localhost 2022 and send "exit" i expect the socket close properly but he dont, and when i send more command the program raise an error
Unhandled exception in spawn: Error writing file: Broken pipe (Errno)
from /usr/lib/crystal/crystal/system/unix/file_descriptor.cr:79:13 in 'unbuffered_write'
from /usr/lib/crystal/io/buffered.cr:122:14 in 'write'
from /usr/lib/crystal/io.cr:1130:7 in 'copy'
from /usr/lib/crystal/process.cr:413:7 in 'copy_io'
from /usr/lib/crystal/process.cr:409:11 in 'copy_io:close_dst'
from /usr/lib/crystal/process.cr:298:17 in '->'
from /usr/lib/crystal/fiber.cr:255:3 in 'run'
from /usr/lib/crystal/fiber.cr:47:34 in '->'
from ???
This is a known issue with Crystal. There is an issue open here:
https://github.com/crystal-lang/crystal/issues/7810

How to terminate (SIGINT) a subprocess in Haskell?

I'm writing a small program in Haskell which manipulates the commands arecordmidi and aplaymidi to record short improvisations on my digital piano through MIDI. I will press the R key, my program will create a new subprocess with the command arecordmidi. When I press R again, I want my recording to stop, by terminating the command arecordmidi.
How do I terminate the arecordmidi subprocess? If in a shell, CTRL+C would stop recording. This is what I want.
I'm using the following code to create the subprocess:
import System.Process
main = do
let rec_command = "arecordmidi -p \"CASIO USB-MIDI\" myRecording.midi"
process <- createProcess (shell rec_command)
-- I could try the following code, but the documentation of System.Process
-- says it's bad to use terminateProcess:
let (_, _, _, processHandle) = process
terminateProcess processHandle
terminateProcess sends a SIGTERM (terminate) signal to the process, which corresponds to the default behavior of the unix command kill, which generally is not what you want when trying to end a process nicely.
Ctrl+C sends the signal SIGINT (interrupt), which many applications handle by an orderly shutdown, and in your case probably results in the arecordmidi process saving outstanding data, and closing any pipes and files.
Looks like the way to send SIGINT with System.Process is with interruptProcessGroupOf.

How to get R to save its state when killed?

I would like to assign some code that will be run when R is killed, for instance, save(list=ls(),file="dump.RData"). I thought this would be by trapping signals, e.g. SIGTERM, as referred to in this post, but there's nothing about signals from the shell in ?conditions.
?conditions does mention user interrupts; you can e.g. catch a Ctrl-C with withCallingHandlers( Sys.sleep(10), interrupt=function (e){cat("I saw that.\n")} ), but this doesn't catch SIGTERM.
How can I do this?
Indeed if you send SIGUSR1 to an R process, it will dump the workspace and stop. On Linux you can do that with
kill -USR1 Rpid
where Rpid is the process id of the R instance you want to stop. You can find it with pgrep for instance.
If R is running in a terminal, you can interrupt it with CTRL-Z and then type
kill -USR1 %

Local network pinging in python

Does anyone know how to use python to ping a local host to see if it is active or not? We (my team and I) have already tried using
os.system("ping 192.168.1.*")
But the response for destination unreachable is the same as the response for the host is up.
Thanks for your help.
Use this ...
import os
hostname = "localhost" #example
response = os.system("ping -n 1 " + hostname)
#and then check the response...
if response == 0:
print(hostname, 'is up!')
else:
print(hostname, 'is down!')
If using this script on unix/Linux replace -n switch with -c !
Thats all :)
I've found that using os.system(...) leads to false positives (as the OP said, 'destination host unreachable' == 0).
As stated before, using subprocess.Popen works. For simplicity I recommend doing that followed by parsing the results. You can easily do this like:
if ('unreachable' in output):
print("Offline")
Just check the various outputs you want to check from ping results. Make a 'this' in 'that' check for it.
Example:
import subprocess
hostname = "10.20.16.30"
output = subprocess.Popen(["ping.exe",hostname],stdout = subprocess.PIPE).communicate()[0]
print(output)
if ('unreachable' in output):
print("Offline")
The best way I could find to do this on Windows, if you don't want to be parsing the output is to use Popen like this:
num = 1
host = "192.168.0.2"
wait = 1000
ping = Popen("ping -n {} -w {} {}".format(num, wait, host),
stdout=PIPE, stderr=PIPE) ## if you don't want it to print it out
exit_code = ping.wait()
if exit_code != 0:
print("Host offline.")
else:
print("Host online.")
This works as expected. The exit code gives no false positives. I've tested it in Python 2.7 and 3.4 on Windows 7 and Windows 10.
I've coded a little program a while back. It might not be the exact thing you are looking for, but you can always run a program on the host OS that opens up a socket on startup. Here is the ping program itself:
# Run this on the PC that want to check if other PC is online.
from socket import *
def pingit(): # defining function for later use
s = socket(AF_INET, SOCK_STREAM) # Creates socket
host = 'localhost' # Enter the IP of the workstation here
port = 80 # Select port which should be pinged
try:
s.connect((host, port)) # tries to connect to the host
except ConnectionRefusedError: # if failed to connect
print("Server offline") # it prints that server is offline
s.close() #closes socket, so it can be re-used
pingit() # restarts whole process
while True: #If connected to host
print("Connected!") # prints message
s.close() # closes socket just in case
exit() # exits program
pingit() #Starts off whole process
And here you have the program that can recieve the ping request:
# this runs on remote pc that is going to be checked
from socket import *
HOST = 'localhost'
PORT = 80
BUFSIZ = 1024
ADDR = (HOST, PORT)
serversock = socket(AF_INET, SOCK_STREAM)
serversock.bind(ADDR)
serversock.listen(2)
while 1:
clientsock, addr = serversock.accept()
serversock.close()
exit()
To run a program without actually showing it, just save the file as .pyw instead of .py.
It makes it invisible until user checks running processes.
Hope it helped you
For simplicity, I use self-made functions based on socket.
def checkHostPort(HOSTNAME, PORT):
"""
check if host is reachable
"""
result = False
try:
destIp = socket.gethostbyname(HOSTNAME)
except:
return result
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(15)
try:
conn = s.connect((destIp, PORT))
result = True
conn.close()
except:
pass
return result
if Ip:Port is reachable, return True
If you wanna to simulate Ping, may refer to ping.py
Try this:
ret = os.system("ping -o -c 3 -W 3000 192.168.1.10")
if ret != 0:
print "Host is not up"
-o waits for only one packet
-W 3000 gives it only 3000 ms to reply to the packet.
-c 3 lets it try a few times so that your ping doesnt run forever
Use this and parse the string output
import subprocess
output = subprocess.Popen(["ping.exe","192.168.1.1"],stdout = subprocess.PIPE).communicate()[0]
How about the request module?
import requests
def ping_server(address):
try:
requests.get(address, timeout=1)
except requests.exceptions.ConnectTimeout:
return False
return True
No need to split urls to remove ports, or test ports, and no localhost false-positive.
Timeout amount doesn't really matter since it only hits the timeout when there is no server, which in my case meant performance no longer mattered. Otherwise, this returns at the speed of a request, which is plenty fast for me.
Timeout waits for the first bit, not total time, in case that matters.

Resources