Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ciao.py exceeds 100% VSZ
#1
Hi all,

I'm having a very strange problem. I have an Arduino Tian that is programmed to send out sensor data to a server every x seconds.
My program run well but after 14,15 hours of operation it stops working and I don't receive datas. The program is fast at the beginning, then after 2 to 3 hours before stopping, it becomes more and more slow with the message "timeout".

I made several commands on the Linux terminal on Arduino OS to try to see what is happening and the program stop when the virtual size memory (vsz) used by ciao.py exceeds 100%.

I deduce that : Probably the process is consuming more virtual memory than there is available RAM, so is swapping...
I think maybe a misuse of the Ciao.py could be at the root of the problem. Or maybe a modification at the program level could correct the problem. So if I can have some help about this..

I put here the screen result of the linux command "top" and "free" after it stop running: [Image: HDsjtes3G4F]
Reply
#2
Without code, it's only guessing. Maybe it's a memory leak.
You can also do a memory profile: https://pypi.org/project/memory_profiler/
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
(Apr-18-2018, 09:40 AM)DeaD_EyE Wrote: Without code, it's only guessing. Maybe it's a memory leak.
You can also do a memory profile: https://pypi.org/project/memory_profiler/

Here is the ciao.py code

import io, os
#import sys,
import signal, re
import logging, json
from threading import Thread
import time
#import atexit

import settings
from utils import *
from ciaoconnector import CiaoConnector
import ciaoserver, ciaomcu

#function to handle OS signals
def signal_handler(signum, frame):
	global logger
	global keepcycling
	logger.info("Received signal %d" % signum)
	keepcycling = False

def __kill_connectors():
	#stopping connectors (managed)
	for name, connector in shd.items():
		logger.info("Sending stop signal to %s" % name)
		connector.stop()

#opening logfile
logger = get_logger("ciao")

#loading configuration for connectors
settings.load_connectors(logger)

#check if connectors have been actually loaded
if not "connectors" in settings.conf or len(settings.conf["connectors"]) == 0:
	logger.critical("No connector enabled, exiting.")
	sys.exit(1)

#creating shared dictionary
shd = {}

#get the board model from cpuinfo
board_model = get_board_model()

#kill previous connectors
kill_connectors_by_pids()

#start ciaoserver thread (to interact with connectors)
server = Thread(name="server", target=ciaoserver.init, args=(settings.conf,shd,))
server.daemon = True
server.start()

mcu = None

if board_model == "ARDUINO YUN" or board_model == "ARDUINO YUN-MINI" or board_model == "ARDUINO CHIWAWA" or board_model == "LININO ONE":
	logger.debug("Ciao MCU Connection starting via standard output")
	mcu = ciaomcu.StdIO(settings, logger)
	mcu.start()
	logger.info("Ciao MCU Connection started via standard output")

elif board_model == "ARDUINO TIAN":
	logger.debug("Ciao MCU Connection starting via serial")
	baud = settings.conf["tian"]["baud"]
	port = settings.conf["tian"]["port"]
	mcu = ciaomcu.Serial(port, baud, logger)
	mcu.start()
	logger.info("Ciao MCU Connection started via serial")

#we start MANAGED connectors after ciaoserver (so they can register properly)
core_version = settings.conf["core"]

for connector, connector_conf in settings.conf['connectors'].items():
	#core_version = settings.conf["core"]
	required_version = connector_conf['core'] if "core" in connector_conf else ">=0.0.0"

	if not ( check_version(required_version, core_version) ):
		logger.error("Required version of Ciao Core [%s] for the connector %s is not compatible with the working Core version [%s]" %(required_version, connector, core_version ))
	else:
		shd[connector] = CiaoConnector(connector, connector_conf, mcu)
		# connector must start after it has been added to shd,
		# it can register only if listed in shd
		shd[connector].start()
		#__attach_connector(connector)

'''
def __attach_connector(connector_name):
	connector_conf = settings.conf['connectors'][connector_name]
	required_version = connector_conf['core'] if "core" in connector_conf else ">=0.0.0"
	if not ( check_version(required_version, core_version) ):
		logger.error("Required version of Ciao Core [%s] for the connector %s is not compatible with the working Core version [%s]" %(required_version, connector, core_version ))
	else:
		shd[connector_name] = CiaoConnector(connector_name, connector_conf, mcu)
		shd[connector_name].start()
'''

#TODO: maybe we can start another thread to control Ciao Core status
#logger.warning(shd)
#variable to "mantain control" over while loop
keepcycling = True

#adding signals management
signal.signal(signal.SIGINT, signal_handler) #ctrl+c
signal.signal(signal.SIGHUP, signal_handler) #SIGHUP - 1
signal.signal(signal.SIGTERM, signal_handler) #SIGTERM - 15

# Before start reading from micro controller, flushes data and cleans the buffer.
# Usually mcu starts to write into buffer before ciao begins to read.
mcu.flush()

while keepcycling:
	try:
		cmd = clean_command(mcu.read())
	except KeyboardInterrupt, e:
		logger.warning("SIGINT received")
	except IOError, e:
		logger.warning("Interrupted system call: %s" %e)
	else:
		if cmd:
			logger.debug("command: %s" % cmd)
			connector, action = is_valid_command(cmd)
			if connector == False:
				if cmd != "run-ciao":
					logger.warning("unknow command: %s" % cmd)
					mcu.write(-1, "unknown_command")
				# else : in this case ciao.py received run-ciao and it must discard the commands
			elif connector == "ciao": #internal commands
				params = cmd.split(";",2)
				if len(params) != 3:
					mcu.write(-1, "unknown_command")
					continue
				if action == "r" and params[2] == "status": #read status
					mcu.write(1, "running")
				elif action == "w" and params[2] == "quit": #stop ciao
					mcu.write(1, "done")
					keepcycling = False
					__kill_connectors()
			elif not connector in settings.conf['connectors']:
				logger.warning("unknown connector: %s" % cmd)
				mcu.write(-1, "unknown_connector")
			elif not connector in shd:
				logger.warning("connector not runnable: %s" % cmd)
				mcu.write(-1, "connector_not_runnable")
			else:
				shd[connector].run(action, cmd)
				'''
				if not connector in shd:
					__attach_connector(connector)
					mcu.write(0, "no_connector")
				else:
					shd[connector].run(action, cmd)
				'''


		# the sleep is really useful to prevent ciao to "cap" all CPU
		# this could be increased/decreased (keep an eye on CPU usage)
		time.sleep(0.01)

logger.info("Exiting")
sys.exit(0)
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020