Categories
Software & Development

.NET WCF The underlying connection was closed

Recently, I spent a few hours solving an issue with sample WCF (Windows Communication Foundation) where my connection from client was closed after the result was received. The error message was following:

The underlying connection was closed: The connection was closed unexpectedly.

There are plenty of blogs explaining how I have to change the client and server configuration (maxRequestLength, maxBufferSize and maxItemsInObjectGraph), e.g. herehere or here. However, in my case the problem was different. If the Service Contractor class defines an operation (method) O1 that returns class C1 (or class that contains property of this type) and O1 returns in fact C2 that derives from C1 you’ll get this error.

The solution as simple as using the KnownType annotation as mentioned in this article. Below the [DataContract] add [KnownType(typeof(C2))].

Categories
Software & Development

Python start process with timeout

The typical scenario to start process and wait for the result takes only a few seconds to write  in other object oriented languages (other than Python) It looks like:

Process p = new Process(command = "my command", redirect_output = True)
p.Wait(timeout = 10)
return p.stdout.result

In Python there is no such functionality provided. You have to check the process using process.poll() method. If there is too much of text in buffer you might achieve situation where your application is deadlocked.

To avoid the deadlock you have to call process.communicate(). However, if there is nothing in stdout the (main) thread waits until the process is finished or the process prints something to stdout. There are a few solutions available that does not work for all scenarios or require unix only modules.

This solution should be platform independent, should work in every situation and should give the process one second to finish gracefully by sending ctrl+c and ctrl+break signals:

def get_cmd_output(self, cmd, timeout = -1, shell = False, cwd = None):

class ProcessHandler:
# there is no subprocess.CREATE_NEW_PROCESS_GROUP available so let's declare it with all necessary constants..
CREATE_NEW_PROCESS_GROUP = 512
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1

def __init__ (self, process, timeout) #, logger):
self.process = process
self.timer = threading.Timer(timeout, self)
self.cancelled = False
self.logger = logger
self.__dict__["result"] = ""

if self.timer.interval > 0:
self.timer.start()

def __setattr__(self, name, val):
# if we set result value then we have to cancel timer
if name == 'result':
self.timer.cancel()

self.__dict__[name] = val

def __getattr__(self, name):
if name == 'result':
if self.cancelled:
return None

return self.__dict__[name]

def __call__ (self):
#self.logger.log("Command timeout (%s seconds) for `%s`" % (timeout, cmd))
self.cancelled = True

# send keyboard interrupt
if platform.system() == 'Windows':
self.logger.log("Sending break signal to windows process")
GenerateConsoleCtrlEvent = ctypes.windll.kernel32.GenerateConsoleCtrlEvent
GenerateConsoleCtrlEvent(ProcessHandler.CTRL_BREAK_EVENT, p.pid)
GenerateConsoleCtrlEvent(ProcessHandler.CTRL_C_EVENT, p.pid)
else:
self.logger.log("Sending break signal to non-windows process")
p.send_signal(ProcessHandler.CTRL_BREAK_EVENT)
p.send_signal(ProcessHandler.CTRL_C_EVENT)

# let's wait 1 second before finally killing the process
time.sleep(1)

# killing brutally
if p.poll() is None:
#self.logger.log("Killing process brutally...")
p.kill()

cmd_split = cmd.split(" ")

p = subprocess.Popen(cmd_split, shell = shell, cwd = cwd, stdout = subprocess.PIPE, stderr = subprocess.PIPE, creationflags = ProcessHandler.CREATE_NEW_PROCESS_GROUP)
h = ProcessHandler(p, timeout) #, logger)
h.result = p.stdout.read()

return h.result