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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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