user78125: I want to send commands to Arduino over USB Serial from my python program and Arduino should send back received command to make sure data wasn't lost. However Arduino randomly stops sending data back. For debugging purposes I made builtin LED blink in the loop function. When Arduino stops sending data the LED slows down blinking (about 2-3 times).
I tried this on Arduino Uno and Arduino Nano to make sure it is not damaged board.
Here is my Python code responsible for communication:

class Communication(ABC):
    def __init__(self) -> None:
        self.history: list = []
        self.response_history: list = []
        self.last_responses: dict = dict()
        self.queue: collections.deque[str] = collections.deque()
        self.is_sending: bool = False
        self.command_recived_condition: threading.Condition = threading.Condition()
    
    def append_commands(self, commands: str) -> None:
        commands = map(lambda x: "c"+x, map(lambda x: x+";", filter(len, commands.split(";"))))
        for command in commands:
            self.queue.append(command)
    
    def append_and_send(self, commands: str) -> None:
        self.append_commands(commands)
        if not self.is_sending:
            self.sender: threading.Thread = threading.Thread(target=Communication.send_commands, args=(self, ))
            self.sender.start()

    
    @abstractmethod
    def send_command(self, command: str) -> bool:
        """ Sends command to the controller, waits for the response and tries again if command was not recived succesfully """
        pass
    
    @abstractmethod
    def listen(self) -> None:
        pass
    
    @abstractmethod
    def check_for_response(self, command: str) -> None:
        pass
    
    def send_commands(self):
        self.is_sending = True
        commands = self.queue
        while len(commands) > 0:
            command = commands.popleft()
            self.send_command(command)
        
        self.is_sending = False
        
    
class Serial_comunication(Communication):
    def __init__(self, port: str) -> None:
        super().__init__()
        self.serialcom = serial.Serial(port, 4800)

        self.listen()

        time.sleep(0.1)
        self.send_command("PING;")
        time.sleep(0.1)
        
    def listen(self) -> None:
        def listen_util() -> None:
            chars = []
            
            while True:
                if self.serialcom.inWaiting() > 0:
                    time.sleep(0.01)
                    try:
                        char: str = self.serialcom.read().decode()
                    except UnicodeDecodeError:
                        print("decoding err")
                        continue
                    print(char, end=" ")

                    if char[-1] == '#':
                        response_str = "".join(chars)
                        category, content = response_str.split("::")
                        self.last_responses[category] = content
                        self.response_history.append(response_str)
                        chars.clear()
                        print("\n", response_str)
                        if category == 'Info: recived':
                            with self.command_recived_condition:
                                self.command_recived_condition.notify()
                    else:
                        chars.append(char)
            
                time.sleep(0.01)
                    
        self.listener = threading.Thread(target=listen_util)
        self.listener.start()
                    
        
        
    def check_for_response(self, command: str) -> None:
        print("check")
        
        if self.last_responses.get('Info: recived') == command:
            print('possitive')
            return True
    
        return False


    def send_command(self, command: str) -> None:

        while True:
            time.sleep(0.1)
            self.serialcom.write(command.encode())
            print("sent", command)

            with self.command_recived_condition:
                self.command_recived_condition.wait()
                print("waited")
            
            if self.check_for_response(command.strip().strip(';')):
                break

And my Arduino Code responsible for communication:
#define INPUT_SIZE 50
char input[INPUT_SIZE + 1];

bool check_for_orders(Order& cmd, char *val, uint8_t& place)
{
    if (Serial.available() > 0)
    {
        // Read input from Serial until ; what means command has ended
        size_t size = Serial.readBytesUntil(';', input, INPUT_SIZE);
        input[size] = 0; // Add null terminator

        Serial.print(F("Info: recived::"));
        delay(10);
        Serial.print(input);
        Serial.print(F("#"));
        Serial.flush();

        // Check if command is not empty
        if (input[0] != 0)
        {
            // syntax is "order:pattern_place:value"
            cmd = static_cast<Order>(atoi(strtok(((char*)input)+1, ":"))); // Get order numer and convert to enum
            place = atoi(strtok(NULL, ":")); // Get place number from input (only 0 or 1 is allowed)
            char *value = strtok(NULL, ":"); // Get value from second part of string
            
            if (value == 0) // If value is empty then syntax is invalid
            {
                return false;
            }

            // Otherwise copy order name and value to c-strings from main function
            strcpy(val, value);
            free(value);

            return true;
        }
        else // Probably never gonna happen
        {
            return false;
        }
    }
    return false;
}

The check_for_orders function is run every time loop function is run.
Here is what python printed when I sent the following commands ["PING;", "c0:0:0;", "c0:1:0; c15:0:100,600,20,2,0,200,255,170,255,200;"]
sent PING;
I n f o :   r e c i v e d : : P I N G # 
 Info: recived::PING
waited
check
possitive
sent c0:0:0;
I n f o :   r e c i v e d : : c 0 : 0 : 0 # 
 Info: recived::c0:0:0
waited
check
possitive
sent c0:1:0;
I n f o :   r e c i v e d : : c 0 : 1 : 0 # 
 Info: recived::c0:1:0
waited
check
possitive
sent c15:0:100,600,20,2,0,200,255,170,255,200;
I n f o :   r e c i v e d : : c 1 5 : 0 : 1 0 0 , 6 0 0 , 2 0 , 2 , 0 , 2 0 0 , 2 5 5 , 1 7 0 , 2 5 5 , 2 0 0 # 
 Info: recived::c15:0:100,600,20,2,0,200,255,170,255,200
waited
check
possitive
sent c1:0:1;
/* and it got stuck */

Do someone know why something here is getting stuck and/or how to solve this problem?

user78125: I removed free(value) - rookie mistake - but that didn't completely solved the problem (but reduced frequency of occurrences).
Seems like declaring array like char val[50] and passing it to function as char* val was a bad idea. I changed array declaration to char *val = new char[50] and now seems like everything works fine.

78125: <p>I want to send commands to Arduino over USB Serial from my python program and Arduino should send back received command to make sure data wasn't lost. However Arduino randomly stops sending data back. For debugging purposes I made builtin LED blink in the loop function. When Arduino stops sending data the LED slows down blinking (about 2-3 times).
I tried this on Arduino Uno and Arduino Nano to make sure it is not damaged board.</p>
<p>Here is my Python code responsible for communication:</p>
<pre class="lang-python prettyprint-override"><code>
class Communication(ABC):
    def __init__(self) -&gt; None:
        self.history: list = []
        self.response_history: list = []
        self.last_responses: dict = dict()
        self.queue: collections.deque[str] = collections.deque()
        self.is_sending: bool = False
        self.command_recived_condition: threading.Condition = threading.Condition()
    
    def append_commands(self, commands: str) -&gt; None:
        commands = map(lambda x: &quot;c&quot;+x, map(lambda x: x+&quot;;&quot;, filter(len, commands.split(&quot;;&quot;))))
        for command in commands:
            self.queue.append(command)
    
    def append_and_send(self, commands: str) -&gt; None:
        self.append_commands(commands)
        if not self.is_sending:
            self.sender: threading.Thread = threading.Thread(target=Communication.send_commands, args=(self, ))
            self.sender.start()

    
    @abstractmethod
    def send_command(self, command: str) -&gt; bool:
        &quot;&quot;&quot; Sends command to the controller, waits for the response and tries again if command was not recived succesfully &quot;&quot;&quot;
        pass
    
    @abstractmethod
    def listen(self) -&gt; None:
        pass
    
    @abstractmethod
    def check_for_response(self, command: str) -&gt; None:
        pass
    
    def send_commands(self):
        self.is_sending = True
        commands = self.queue
        while len(commands) &gt; 0:
            command = commands.popleft()
            self.send_command(command)
        
        self.is_sending = False
        
    
class Serial_comunication(Communication):
    def __init__(self, port: str) -&gt; None:
        super().__init__()
        self.serialcom = serial.Serial(port, 4800)

        self.listen()

        time.sleep(0.1)
        self.send_command(&quot;PING;&quot;)
        time.sleep(0.1)
        
    def listen(self) -&gt; None:
        def listen_util() -&gt; None:
            chars = []
            
            while True:
                if self.serialcom.inWaiting() &gt; 0:
                    time.sleep(0.01)
                    try:
                        char: str = self.serialcom.read().decode()
                    except UnicodeDecodeError:
                        print(&quot;decoding err&quot;)
                        continue
                    print(char, end=&quot; &quot;)

                    if char[-1] == '#':
                        response_str = &quot;&quot;.join(chars)
                        category, content = response_str.split(&quot;::&quot;)
                        self.last_responses[category] = content
                        self.response_history.append(response_str)
                        chars.clear()
                        print(&quot;\n&quot;, response_str)
                        if category == 'Info: recived':
                            with self.command_recived_condition:
                                self.command_recived_condition.notify()
                    else:
                        chars.append(char)
            
                time.sleep(0.01)
                    
        self.listener = threading.Thread(target=listen_util)
        self.listener.start()
                    
        
        
    def check_for_response(self, command: str) -&gt; None:
        print(&quot;check&quot;)
        
        if self.last_responses.get('Info: recived') == command:
            print('possitive')
            return True
    
        return False


    def send_command(self, command: str) -&gt; None:

        while True:
            time.sleep(0.1)
            self.serialcom.write(command.encode())
            print(&quot;sent&quot;, command)

            with self.command_recived_condition:
                self.command_recived_condition.wait()
                print(&quot;waited&quot;)
            
            if self.check_for_response(command.strip().strip(';')):
                break
</code></pre>
<p>And my Arduino Code responsible for communication:</p>
<pre class="lang-cpp prettyprint-override"><code>#define INPUT_SIZE 50
char input[INPUT_SIZE + 1];

bool check_for_orders(Order&amp; cmd, char *val, uint8_t&amp; place)
{
    if (Serial.available() &gt; 0)
    {
        // Read input from Serial until ; what means command has ended
        size_t size = Serial.readBytesUntil(';', input, INPUT_SIZE);
        input[size] = 0; // Add null terminator

        Serial.print(F(&quot;Info: recived::&quot;));
        delay(10);
        Serial.print(input);
        Serial.print(F(&quot;#&quot;));
        Serial.flush();

        // Check if command is not empty
        if (input[0] != 0)
        {
            // syntax is &quot;order:pattern_place:value&quot;
            cmd = static_cast&lt;Order&gt;(atoi(strtok(((char*)input)+1, &quot;:&quot;))); // Get order numer and convert to enum
            place = atoi(strtok(NULL, &quot;:&quot;)); // Get place number from input (only 0 or 1 is allowed)
            char *value = strtok(NULL, &quot;:&quot;); // Get value from second part of string
            
            if (value == 0) // If value is empty then syntax is invalid
            {
                return false;
            }

            // Otherwise copy order name and value to c-strings from main function
            strcpy(val, value);
            free(value);

            return true;
        }
        else // Probably never gonna happen
        {
            return false;
        }
    }
    return false;
}
</code></pre>
<p>The check_for_orders function is run every time loop function is run.</p>
<p>Here is what python printed when I sent the following commands [&quot;PING;&quot;, &quot;c0:0:0;&quot;, &quot;c0:1:0; c15:0:100,600,20,2,0,200,255,170,255,200;&quot;]</p>
<pre><code>sent PING;
I n f o :   r e c i v e d : : P I N G # 
 Info: recived::PING
waited
check
possitive
sent c0:0:0;
I n f o :   r e c i v e d : : c 0 : 0 : 0 # 
 Info: recived::c0:0:0
waited
check
possitive
sent c0:1:0;
I n f o :   r e c i v e d : : c 0 : 1 : 0 # 
 Info: recived::c0:1:0
waited
check
possitive
sent c15:0:100,600,20,2,0,200,255,170,255,200;
I n f o :   r e c i v e d : : c 1 5 : 0 : 1 0 0 , 6 0 0 , 2 0 , 2 , 0 , 2 0 0 , 2 5 5 , 1 7 0 , 2 5 5 , 2 0 0 # 
 Info: recived::c15:0:100,600,20,2,0,200,255,170,255,200
waited
check
possitive
sent c1:0:1;
/* and it got stuck */
</code></pre>
<p>Do someone know why something here is getting stuck and/or how to solve this problem?</p>
 78125: <p>I removed <code>free(value)</code> - rookie mistake - but that didn't completely solved the problem (but reduced frequency of occurrences).
Seems like declaring array like <code>char val[50]</code> and passing it to function as <code>char* val</code> was a bad idea. I changed array declaration to <code>char *val = new char[50]</code> and now seems like everything works fine.</p>
