Vermehrte Abstürze seit der 5.2?

Ich will das Thema hier nicht verwässern. Das exec Problem hatte ich auch. Bei mir läuft IPS auf dem Raspi 3B unter Stretch. Unter dem Strich habe ich das exec Problem behoben, in dem ich konsequent Fehlermeldungen beseitigt habe. Im Laufe der Zeit hatte sich da einiges angesammelt. Z. B. RFC Kostenmanager, ältere Skripte die ich nicht sofort tot gelegt hatte. Kam durch die Umstellungen der 4 auf die 5.x. Beim Auftreten des Problems war bei mir der verfügbare Speicher auf dem Raspi nahe 0. Eine Systematik konnte ich nicht erkennen (bestimmtes Gerät, Skript, Instanz). Seit meinen Bereinigungsaktionen ist dieser Effekt mit dem Speicher nicht mehr aufgetreten. Er bleibt sehr konstant. Dieser Fehler hatte mich längere Zeit begleitet.

Die hier genannten Abstürze hatte ich erst wieder seit der 5.2 vom 6.9. Es scheint bei mir wie schon gennant mit socket_read zusammen zu hängen. Allerdings läuft mein System erst seit ein paar Tagen wieder stabil.
Die Anbindung der Wetterstation, die diese Abstürze (höchstwahrscheinlich) verursacht hat, ist über WLAN per MESH angebunden. Hin und wieder gibt es da Aussetzer, da die Daten aus der letzten Ecke des Gartens kommen. Evtl. treten die Probleme ja nur mit den socket_XXX Befehlen unter PHP auf. Normal verwende ich den Client Socket von Symcon. Aber bei der Wetterstation und in meinem OneWire Skript (fragt einen OWNET Server ab), werden die PHP socket_XXX Befehle verwendet.

Bei meinem Absturz muss ich mich korrigieren. Ich hatte noch die 5.1 drauf… ich nahm fälschlicherweise an ich hätte schon zur 5.2 gewechselt.

Die 5.1 lief bestimmt 2 Monate ohne Restart. Auch habe ich keine grossartige Änderung vorgenommen. Dann auf einmal in der Nacht laut Log der Verlust der Connection zum EIB Gateway und das war es.

Jetzt habe ich die 5.2 stable drauf mit VoiP Modul und bis jetzt läuft es stabil.

Das merkwürdige ist der Umstand das die Abstürze mal kommen und dann meist mehrere hintereinander und dann wieder Wochen Ruhe ist.

Um hier effektiv voran zu kommen bräuchte ich leider irgendwie einen GDB Backtrace (für die Linux’ler) oder weitere Windows MiniDumps (@Slummi: Danke, deine habe ich :))

Aktuell gibt es leider keinen richtigen Anhaltspunkt was das Problem sein könnte.

paresy

Genau, darum habe ich mich bisher auch zurückgehalten.

Ich fahre die 5.3 Beta schon von Anfang an und da hatte ich keine Probleme, kam erst so in den letzen 3-4 Wochen.
Habe heute nochmal auf die letzte Version upgedated. Schauen wir mal. Sollte sich das Intervall der Abstürze weiterhin so gestalten dann schaue ich das ich Dir den GDB Backtrace zur Verfügung stelle!

Gruß Heiko

PS: das einzige was ich davor im „größeren“ Stil geändert habe ist das Philips Hue Modul zu tauschen. @KaiS: bitte nicht verkehrt verstehen, absolut keine Kritik an Dich oder dem Modul. VoIP hatte ich erst nach den vereinzelten Abstürzen installiert und jetzt wieder gelöscht! Keine weiteren Module installiert, nur immer alle Updates mitgenommen :wink:

Ich bin gerade wieder ein Bisschen am rum testen und versuche einen Absturz zu provozieren. Bis jetzt aber ohne Erfolg… :banghead:

In der Zwischenzeit habe ich mal meine Ereignis-Logs vom Server durchforstet.
Bei den Abstürzen wird immer die php7ts.dll als fehlerhaftes Modul aufgeführt. Das ist aber vermutlich wenig überraschend und geht auch aus den Mini Dumps hervor.

Was ich außerdem sehe, sind immer die folgenden beiden Fehler beim Start des Dienstes:


php[3232]
PHP Warning: PHP Startup: Unable to load dynamic library 'php_pdo_oci.dll' (tried: C:\IP-Symcon\ext\php_pdo_oci.dll (Das angegebene Modul wurde nicht gefunden.), C:\IP-Symcon\ext\php_php_pdo_oci.dll.dll (Das angegebene Modul wurde nicht gefunden.)) (C:\IP-Symcon\ips.exe)


php[3232]
PHP Warning: PHP Startup: Unable to load dynamic library 'php_pdo_firebird.dll' (tried: C:\IP-Symcon\ext\php_pdo_firebird.dll (Das angegebene Modul wurde nicht gefunden.), C:\IP-Symcon\ext\php_php_pdo_firebird.dll.dll (Das angegebene Modul wurde nicht gefunden.)) (C:\IP-Symcon\ips.exe)

Keine Ahnung, was es damit auf sich hat.
Ich werde mal weiter versuchen den Dienst in die Knie zu zwingen. :wink:

Gruß
Slummi

Hallo paresy,

so, hatte vorhin gdb angeschmissen. Innerhalb von Minuten ist das System abgeschmiert. Murphy? Ich hab mal Logs und gdb.txt angehängt. Ich hätte das vorhin nicht schreiben sollen…
Komischerweise ist da wohl das ownet Skript wieder beteiligt,. Siehe auch in der IPSLogger.xxx.xml. Der Fehler ist genau bei den socket_XX Befehlen aufgetaucht.
Werde mal weiter gdb mitlaufen lassen. Mal schauen, ob da noch was kommt.

Anbei nochmal die ownet.php:


<?php
// Anmerkung: Apassungen für IPSymcon
// zuletzt geprüft 2017-01-28


/*
VERSION: 2007.01.11 - 17:05  BRST

Copyright (c) 2007 Spadim Technology / Brazil. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
	
OWFS is an open source project developed by Paul Alfille and hosted at
http://www.owfs.org

 mailto:roberto@spadim.com.br
	www.spadim.com.br
	
	
*/


/*
from php.net
pack($format, ... )	
	format='i' : signed integer (machine dependent size and byte order)
 we will have problems with 64bits ?? using this-> pack / unpack builtin function
 
 
from linux sources
#include <arpa/inet.h>

uint32_t			(pack format = 'N')
htonl(uint32_t hostlong);

uint16_t			(pack format = 'n')
htons(uint16_t hostshort);

uint32_t			(pack format = 'n')
ntohl(uint32_t netlong);

uint16_t			(pack format = 'n')
ntohs(uint16_t netshort);

from http://www.linuxjournal.com/article/6788
	IP's byte order also is big endian.
*/

// Constants for the OWNet class
define('OWNET_DEFAULT_HOST'	,'127.0.0.1');
define('OWNET_DEFAULT_PORT'	,4304);
define('OWNET_LINK_TYPE_SOCKET'	,0);
define('OWNET_LINK_TYPE_STREAM'	,1);
define('OWNET_LINK_TYPE_TCP'	,0);
define('OWNET_LINK_TYPE_UDP'	,1);

/*
Constants for the owserver api message types. from ow.h
enum msg_classification {
    msg_error,
    msg_nop,
    msg_read,
    msg_write,
    msg_dir,
    msg_size,			// No longer used, leave here to compatibility
    msg_presence,
};
*/
define('OWNET_MSG_ERROR'	,0);
define('OWNET_MSG_NOP'		,1);
define('OWNET_MSG_READ'		,2);
define('OWNET_MSG_WRITE'	,3);
define('OWNET_MSG_DIR'		,4);
define('OWNET_MSG_SIZE'		,5);
define('OWNET_MSG_PRESENCE'	,6);
define('OWNET_MSG_DIR_ALL'	,7);
define('OWNET_MSG_READ_ANY'	,99999);


if (!defined('TCP_NODELAY'))
	define('TCP_NODELAY',1);
if (!defined('IPPROTO_TCP'))
	define('IPPROTO_TCP',6);

$OWNET_GLOBAL_CACHE_STRUCTURE=array();	// cache value types length read write....
class OWNet{
	protected $link=0;
	protected $host='';
	protected $port=0;
	protected $sock_type=OWNET_LINK_TYPE_TCP;
	protected $link_type=OWNET_LINK_TYPE_SOCKET;
	protected $link_connected=false;
	protected $timeout=0;
	protected $use_swig_dir=true;

	function __construct($host='',$timeout=5,$use_swig_dir=true){
		// just set default configurations
		$this->setHost($host);
		$this->timeout=abs((double)$timeout);
		$this->use_swig_dir=(bool)$use_swig_dir;
	}
	function setTimeout($timeout=5){
		$this->timeout=abs((double)$timeout);
	}
	function getTimeout(){
		return($this->timeout);
	}
	function setUseSwigDir($use){
		$this->use_swig_dir=(bool)$use;
	}
	function getUseSwigDir(){
		return($this->use_swig_dir);
	}
	function setHost($host=''){	
		// host must be "anything://host:port" or "anything://host" OR 'anything that don't parse_url and get default values'
		// use "stream://host:port" or "ow-stream://host:port" to prefer stream instead sockets
		$tmp_path	=@parse_url($host);	// get URL information from host
		if (!isset($tmp_path['scheme']))
			$tmp_path	=@parse_url("tcp://$host");
		
		$this->host	=	(!isset($tmp_path['host'])?OWNET_DEFAULT_HOST:$tmp_path['host']);	// if don't have host get default host
		$this->port	=(int)	(!isset($tmp_path['port'])?OWNET_DEFAULT_PORT:$tmp_path['port']);	// if don't have port get default port
		$prefer_sock	=(isset($tmp_path['scheme'])?
			($tmp_path['scheme']!='stream' && $tmp_path['scheme']!='ow-stream' &&
			 $tmp_path['scheme']!='stream-udp' && $tmp_path['scheme']!='ow-stream-udp')
			:true);	// check if prefer using streams instead socket
		if (strpos($tmp_path['scheme'],'udp')!==false)
			$this->sock_type=OWNET_LINK_TYPE_UDP;
		else
			$this->sock_type=OWNET_LINK_TYPE_TCP;
		unset($tmp_path);
		
		if (function_exists('socket_connect') && $prefer_sock){	
			$this->link_type=OWNET_LINK_TYPE_SOCKET;	// prefer socks
		}else{
			$this->link_type=OWNET_LINK_TYPE_STREAM;	// prefer stream
		}
		$this->link_connected		=false;
		return(true);
	}
	function getHost(){
		// return and URI that can be used with setHost again
		if ($this->link_type==OWNET_LINK_TYPE_STREAM)	
			return('ow-stream'.($this->sock_type==OWNET_LINK_TYPE_UDP?'-udp':'').'://'.$this->host.':'.$this->port);	// using streams
		return('ow'.($this->sock_type==OWNET_LINK_TYPE_UDP?'-udp':'').'://'.$this->host.':'.$this->port);			// using sockets if possible
	}
	protected function pack_htonl( $val ){
		// builtin function to use htonl, big endian style
		$bval	=str_pad(decbin(bcadd($val,0,0)),8*4,'0',STR_PAD_LEFT);
		$b1	=bindec(substr($bval,0,8));
		$b2	=bindec(substr($bval,8,8));
		$b3	=bindec(substr($bval,16,8));
		$b4	=bindec(substr($bval,24,8));
		return(chr($b1).chr($b2).chr($b3).chr($b4));
	}
	protected function unpack_ntohl($str){
		// builtin function to use ntohl, big endian style, not shure if it's right
		$size=strlen($str)/4;
		$ret=array();
		for($i=0;$i<$size;$i++){
			$bval	=substr($str,$i*4,4);
			$b1	=ord(substr($bval,0,1));
			$b2	=ord(substr($bval,1,1));
			$b3	=ord(substr($bval,2,1));
			$b4	=ord(substr($bval,3,1));
			$value	=$b4 + ($b3<<8) + ($b2<<16) + ($b1<<24);
			$ret[$i]=$value;
		}
		return($ret);
	}
	private function disconnect(){
		// disconnect link
		if ($this->link_type==OWNET_LINK_TYPE_SOCKET){		// socket
			@socket_set_block($this->link);
			if ($this->sock_type==OWNET_LINK_TYPE_TCP)
				@socket_shutdown($this->link,2);
			@socket_close($this->link);
		}else{
			@fclose($this->link);				// streams
		}
		$this->link=NULL;
		$this->link_connected=false;
	}
	private function connect(){
		// connect with sockets or stream
		if ($this->link_connected)
			return(true);		// if connected don't continue
		if ($this->link_type==OWNET_LINK_TYPE_SOCKET){		// socket
			if ($this->sock_type==OWNET_LINK_TYPE_TCP){
				$this->link=@socket_create(AF_INET, SOCK_STREAM, SOL_TCP);		// create socket
				if ($this->link){
					@socket_set_block($this->link);					// set it to blocking
					$ok=@socket_connect($this->link,$this->host,$this->port);	// try to connect
					if (!$ok){
						$errno	=@socket_last_error();				// get error when connecting
						$errstr	=@socket_strerror(socket_last_error());
						trigger_error("Can't create socket [ow://".$this->host.":".$this->port."], errno: $errno, error: $errstr",E_USER_NOTICE);
						@socket_shutdown($this->link,2);			// unload socket
						@socket_close($this->link);
						$this->link=NULL;
						return(false);						// return false on error or can't connect
					}	// socket created and connected
				}else{
					$errno	=@socket_last_error();					// get error when creating socket
					$errstr	=@socket_strerror(@socket_last_error());
					trigger_error("Can't create socket [ow://".$this->host.":".$this->port."], errno: $errno, error: $errstr",E_USER_NOTICE);
					return(false);							// return false on error or can't connect
				}
			}else{	// udp
				$this->link=@socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);		// create socket
				if ($this->link){
					@socket_set_block($this->link);					// set it to blocking
				}else{
					$errno	=@socket_last_error();					// get error when creating socket
					$errstr	=@socket_strerror(@socket_last_error());
					trigger_error("Can't create socket [ow-udp://".$this->host.":".$this->port."], errno: $errno, error: $errstr",E_USER_NOTICE);
					return(false);							// return false on error or can't connect
				}
			}
		}else{							// stream
			$this->link	=@stream_socket_client(
				($this->sock_type==OWNET_LINK_TYPE_TCP?'tcp://':'udp://').
				$this->host.":".$this->port, $errno, $errstr, $this->timeout);		// connect with streams, could be with fsockopen but stream_socket_client is faster (we will use PHP 5+)
			if (!$this->link){
				trigger_error("Can't create stream [ow-stream".($this->sock_type!=OWNET_LINK_TYPE_TCP?'-udp':'')."://".$this->host.":".$this->port."], errno: $errno, error: $errstr",E_USER_NOTICE);
				return(false);							// return false on error or can't connect
			}
		}
		$this->set_link_options();	// set socket options or stream options
		$this->link_connected=true;
		return(true);			// ok 
	}
	private function set_link_options(){
		// set link options
		if (!$this->link_connected)
			return(false);
		if ($this->link_type==OWNET_LINK_TYPE_SOCKET){		// socket
			socket_set_block(	$this->link);				// set blocking mode
			if ($this->sock_type==OWNET_LINK_TYPE_TCP){
				socket_set_option(	$this->link,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0, "usec"=>100));	// receive timeout
				socket_set_option(	$this->link,SOL_SOCKET, SO_SNDTIMEO, array("sec"=>0, "usec"=>100));	// send timeout
				socket_set_option($this->link, SOL_SOCKET, SO_REUSEADDR, 1);	// reuse address
				socket_set_option($this->link, SOL_SOCKET, SO_OOBINLINE, 1);	// out off band inline
				@socket_set_option($this->link, IPPROTO_TCP, TCP_NODELAY, 1);	// no delay  can have bug with windows?!
			}
			socket_set_option($this->link, SOL_SOCKET, SO_RCVBUF, 8192);	// set receive buffer
			socket_set_option($this->link, SOL_SOCKET, SO_SNDBUF, 8192);	// set send buffer
		}else{
			stream_set_timeout($this->link		,20);			// set timeout
			stream_set_blocking($this->link		,1);			// set blocking mode
			stream_set_write_buffer($this->link	,0);			// flush everything directly without buffer (faster than with buffer=8192)
		}
		return(true);
	}
	private function get_msg($msg_size=24){		// return false on error
		// get messagem from server
		$num_changed_sockets	=0;
		$read_data		='';
		$last_read		=microtime(1);
		$t1=intval($this->timeout);
		$t2=($this->timeout*1000000)%1000000;
		while ($num_changed_sockets<=0){	// can loop forever? owserver must send something! or disconnect!
			$read=array($this->link);
			$write = NULL;
			$except = NULL;

			if ($this->link_type==OWNET_LINK_TYPE_SOCKET)
				$num_changed_sockets = socket_select($read, $write, $except, $t1,$t2);	// use socket_select
			else
				$num_changed_sockets = stream_select($read, $write, $except, $t1,$t2);	// use stream_select
			if ($num_changed_sockets===false){	// error handling select
				$this->disconnect();
				trigger_error("Error handling get_msg#1",E_USER_NOTICE);
				return(false);			// return false when have error
			}elseif($num_changed_sockets>0){	// we can read!
				if ($this->link_type==OWNET_LINK_TYPE_SOCKET){
					if ($this->sock_type==OWNET_LINK_TYPE_TCP){
						$read_data=socket_read($this->link,$msg_size,PHP_BINARY_READ);	// read with sockets
					}else{
						$ret=socket_recvfrom($this->link,$read_data,$msg_size,$tmp_host,$tmp_port);	// read with sockets
						if ($ret>0){
							$this->host=$tmp_host;
							$this->port=$tmp_port;
						}
					}
				}else
					$read_data=fread($this->link,$msg_size);			// read with streams
				if ($read_data==''){		// disconnected :'(
					$this->disconnect();
					trigger_error("Disconnected",E_USER_NOTICE);
					return(false);			// return false when have error
				}else
					$last_read		=microtime(1);
				break;
			}else
				break;
			if (microtime(1)-$last_read>$this->timeout)
				break;
		}
		return($read_data);			// return data
	}
	private function send_msg($string){	// return false on error and true on success, trigger error on disconnection
		// send message to server
		if (!$this->link_connected)
			return(false);
		$num_changed_sockets=0;
		while ($num_changed_sockets<=0){
			$write=array($this->link);
			
			$v4 = 0;
			$v5 = 1000;
			$read = NULL;
	  	 	$except = NULL;
			
			if ($this->link_type==OWNET_LINK_TYPE_SOCKET)
				// $num_changed_sockets = socket_select($read = NULL, $write , $except = NULL, 0,1000);	// use socket_select
            $num_changed_sockets = socket_select($read, $write , $except, $v4, $v5);	// use socket_select
			else
				// $num_changed_sockets = stream_select($read = NULL, $write , $except = NULL, 0,1000);	// use stream_select
            $num_changed_sockets = stream_select($read, $write , $except, $v4, $v5);	// use stream_select
			if ($num_changed_sockets===false){		// error handling
				$this->disconnect();
				trigger_error("Error handling send_msg#1",E_USER_NOTICE);
				return(false);				// return false on error
			}
		}
		$size=strlen($string);
		$sent=0;
		while($sent<$size){
			// we will not use select, using can be slower, and without work! :D
			if ($this->link_type==OWNET_LINK_TYPE_SOCKET){
				if ($this->sock_type==OWNET_LINK_TYPE_TCP)
					$ret=socket_write($this->link, $string, strlen($string));				// write and get sent bytes
				else
					$ret=socket_sendto($this->link, $string, strlen($string),0,$this->host,$this->port);	// write and get sent bytes
			}else
				$ret=fwrite($this->link,$string,strlen($string));		// write and get sent bytes
			if ($ret===false){
				// error sending
				$this->disconnect();
				trigger_error("Error writing send_msg#1",E_USER_NOTICE);
				return(false);				// return false on error
			}
			$sent+=$ret;	// add sent bytes
		}
		return(true);		// ok everything sent
	}
	function read($path,$parse_value=true){
		// return NULL on error or no file
		// if $parse_value return php parsed value type (boolean,double,string), if not return an string value
		return($this->get($path,OWNET_MSG_READ,false,$parse_value));		// return get with right flags
	}
	function dir($path){
		// return NULL on error or no directory
		// return numeric array starting from 0 with directory list
		return($this->get($path,OWNET_MSG_DIR_ALL,false,false));		// return get with right flags
	}
	function presence($path){
		// return NULL on error
		// return true or false on success
		return($this->get($path,OWNET_MSG_PRESENCE,false,false));	// return get with right flags
	}
	function get($path='/',$get_type=OWNET_MSG_READ,$return_full_info_array=false,$parse_php_type=true){		// return NULL on error
		// path = path of file or directory
		// get_type = 	OWNET_MSG_READ_ANY 	(READ AND DIR)
		//		OWNET_MSG_READ		read an file
		//		OWNET_MSG_DIR or OWNET_MSG_DIR_ALL		read an directory (output is an array)
		//		OWNET_MSG_PRESENCE	check presence output is true or false
		// return_full_info_array	if true return everything from comunication and unit if variables is an temperature, ['data'] is returned data and ['data_php'] is an parsed data in (double) or (string) types
		// parse_php_type		if true try to get right data_php variable type
	
		// return NULL on error or not founded
		// return an array on OWNET_MSG_DIR or when return_full_info_array=true
		// return true or false when OWNET_MSG_PRESENCE
	
		$path=trim($path);	// trim path
		if ($get_type==OWNET_MSG_READ_ANY){
					// getting first read
			$ret=$this->get($path,OWNET_MSG_READ,$return_full_info_array,$parse_php_type);
			if ($ret!==NULL)
				return($ret);	// ok we get and result
			return($this->get($path,OWNET_MSG_DIR_ALL,$return_full_info_array,$parse_php_type));	// return dir
		}
		if ($get_type!=OWNET_MSG_DIR && $get_type!=OWNET_MSG_DIR_ALL){
			if (substr($path,strlen($path)-1,1)=='/')	// isn't a dir, dir must end with characters != '/'
				return(NULL);
		}
		$this->disconnect();		// be sure that we are disconnected
		$this->connect();		// try to connect
		if (!$this->link_connected){
			trigger_error("Can't connect get#1",E_USER_NOTICE);
			return(NULL);
		}
		// get value
		if ($get_type==OWNET_MSG_DIR || $get_type==OWNET_MSG_DIR_ALL){	// get right send function
			$msg=$this->pack($get_type		,strlen($path)+1,0	);
		}elseif ($get_type==OWNET_MSG_PRESENCE){
			$msg=$this->pack(OWNET_MSG_PRESENCE	,strlen($path)+1,0	);
		}else{
			$get_type=OWNET_MSG_READ;
			$msg=$this->pack(OWNET_MSG_READ		,strlen($path)+1,8192	);
		}
		if ( $this->send_msg($msg)===false ){
			trigger_error("Can't write to resource get#1",E_USER_NOTICE);
			return(NULL);	// error sending
		}
		if ( $this->send_msg($path.chr(0))===false){
			trigger_error("Can't write to resource get#2",E_USER_NOTICE);
			return(NULL);	// error sending
		}
		if ($parse_php_type)
			global $OWNET_GLOBAL_CACHE_STRUCTURE;	// we will use for parse_php_type
		// get return
		$return=NULL;		// set to NULL if nothing returned
		while(1){
			unset($ret,$data,$tmp_ret,$start,$data_len);
			$data='';$tmp_ret='';
			$start=microtime(1);
			while(1){
				$tmp_ret=$this->get_msg(24);
				if ($tmp_ret===false){
					trigger_error("Can't read from resource get#3",E_USER_NOTICE);
					$this->disconnect();
					return(NULL);
				}
				if (strlen($tmp_ret)>0)	$start=microtime(1);
				$data.=$tmp_ret;
				unset($tmp_ret);
				if(strlen($data)>=24 || (microtime(1)-$start)>$this->timeout)
					break;
			}
			$ret=$this->unpack(substr($data,0,24));	// unpack 24bytes into 6 data 
			if (count($ret)<6){
				if ($get_type==OWNET_MSG_DIR_ALL)	// old servers
					return($this->get($path,OWNET_MSG_DIR,$return_full_info_array,$parse_php_type));	
				$data=substr($data,0,24);
				trigger_error("Error unpacking data get#1 [".strlen($data)."] ".$data,E_USER_NOTICE);
				$this->disconnect();
				return(NULL);
			}
			if ($get_type==OWNET_MSG_PRESENCE){
				// check presence
				if (!isset($ret[2]))
					return(NULL);	// error ?! maybe not (count < 6)
				return($ret[2]===0);	// ret[2]!=0 => not present
			}
			$data=substr($data,24);		// if any data was read with more than 24 bytes
			if (!isset($ret[1]))
				$ret[1]=false;		// just to be sure that will not get into $ret parsing
			if ($ret[1]>0){
				if ($get_type==OWNET_MSG_DIR || $get_type==OWNET_MSG_DIR_ALL)	// reading directory use $ret[1] for read data
					$data_len=$ret[1];
				else
					$data_len=$ret[2];	// reading file use $ret[2] for read data
				$tmp_ret='';
				$start=microtime(1);		// set start time for timeout read
				if ($data_len>0)
					while(1){
						$tmp_ret=$this->get_msg($data_len);
						if ($tmp_ret===false){
							trigger_error("Can't read from resource get#4",E_USER_NOTICE);	// error receiving
							$this->disconnect();
							return(NULL);		// return NULL on error
						}
						if (strlen($tmp_ret)>0)	$start=microtime(1);
						$data.=$tmp_ret;unset($tmp_ret);
						if(strlen($data)>=$data_len || (microtime(1)-$start)>$this->timeout)	// timedout or got every data that we need
							break;
					}
				if (!$return_full_info_array && strlen($data)!=$data_len){	// if just return value and data < data_len return as an error
					trigger_error("Can't read full data get#1",E_USER_NOTICE);
					$this->disconnect();
					return(NULL);		// return NULL on error
				}
				if ($get_type==OWNET_MSG_DIR){	// reading dir
					$ret['data']	=$data;
					$ret['data_len']=strlen($data);
					$ret['data_php']=substr($data,0,$ret[4]);	// ret[4] is the right filename size ?! it's work :D
					if ($return===NULL)
						$return=array();	// se return as an array to get values
					if ($return_full_info_array)
						$return[]=$ret;		// return an array
					else
						$return[]=$ret['data_php'];	// return file name
					// continue while...
				}else{
					$ret['data']	=substr($data,0,$data_len);	// data_php length is the same as $ret[2]
					$ret['data_len']=strlen($data);
					$this->disconnect();		// disconnect from server
					$type=false;			// check type?
					if ($parse_php_type && $get_type!=OWNET_MSG_DIR_ALL){
						$tmp		=explode('/',$path);$c=count($tmp)-1;
						if ($c>0){		// must be something like '/dir/file'	array('dir', 'file'), count()-1 = 1 > 0
							$variavel	=$tmp[$c];		// get last two uri args
							$ow		=$tmp[$c-1];
							unset($tmp);
							if (preg_match('/([0-9A-F]{2})[\.]{0,1}[0-9A-F]{12}/',$ow,$tmp)){	// check if ow is an OW id ("XX.ZZZZZZZZZZZZ or XXZZZZZZZZZZZZ")
								$tmp=$tmp[1];
								if (!isset($OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel])){	// check if we have structure information
									$tmp_v=@$this->get("/structure/$tmp/$variavel",OWNET_MSG_READ,false,false);	// get estrutucture information
									if ($tmp_v!==NULL){
										$tmp_v=explode(',',$tmp_v);						// ok :D we will get real php values now!
										$OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel]=$tmp_v;
										$type=$tmp_v;
									}
								}else
									$type=$OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel];
							}
						}
						unset($tmp,$tmp_v,$variavel,$ow,$c);
					}
					if ($type!==false){
						// get real php values
						$ret['data_php']=$ret['data'];
						if($type[0]=='i'){
							$ret['data_php']=bcadd($ret['data_php'],0,0);	// integer (using bcmath for bigger precision)
						}elseif($type[0]=='u'){
							$ret['data_php']=bcadd($ret['data_php'],0,0);	// unsigned integer (using bcmath for bigger precision)
							// MAJA 2017-01-28 - Tippfehler im Original
							// if (bccmp($ret['data_php'],0,0)==-1){
							if (bccomp($ret['data_php'],0,0)==-1){
								$ret['data_php']=substr($ret['data_php'],1);		// be shure that it's unsigned
							}
						}elseif(in_array($type[0],array('f','t',chr(152)))){
							$ret['data_php']=(double)$ret['data_php'];	// using float (double) values, maybe sprinf("%.50f",$value) could get an string representation
							if ($return_full_info_array){
								if ($type[0]=='t'){			// temperature (last owserver versions... maybe an 'v' for volts and 'A' for amps could be implemented)
									// we can't cache cause server may restart or change configurations while we have old cache information, here we will have +- .1 seconds of performace lost, set return full information off if you don't want it
									$tmp_v=@$this->get("/settings/units/temperature_scale",OWNET_MSG_READ,false,false);	// get server current scale
									if ($tmp_v!==NULL)		// just for compatible with old owservers
										$ret['unit']=$tmp_v;	// use unit if return full information
								}
							}
						}elseif(in_array($type[0],array('a','b','d'))){
							$ret['data_php']=(string)$ret['data_php'];	// string (maybe without it could work too, but's it's pretty :D ) 
						}elseif($type[0]=='y'){
							$ret['data_php']=($ret['data_php']==1?true:false);	// boolean content
						}	// another contents are parsed as string too
					}else{
						$ret['data_php']=&$ret['data'];		// we will use not parsed values (we use it when getting structure information! or setting $parse_php_type=false)
					}
					if ($get_type==OWNET_MSG_DIR_ALL){
						$return=& $ret;
						break;
					}
					if ($return_full_info_array){
						return($ret);			// return array
					}else{
						return($ret['data_php']);	// return just php parsed value
					}
				}
			}else{
				break;
			}
		}
		$this->disconnect();	// disconnect from server (dir listing)
		if ($get_type==OWNET_MSG_DIR_ALL && $return===NULL)	// old servers
			return($this->get($path,OWNET_MSG_DIR,$return_full_info_array,$parse_php_type));	
		if ($return!==NULL){
			if ($this->use_swig_dir && !$return_full_info_array && $get_type==OWNET_MSG_DIR)
				if (is_array($return))
					$return=implode(',',$return);
			if ($this->use_swig_dir==false && $get_type==OWNET_MSG_DIR_ALL){
				if ($return_full_info_array){
					$tmp=explode(',',$return['data_php']);
					$r=array();
					for ($i=0;$i<count($tmp);$i++)
						$r[]=array(
							0=>$return[0],
							1=>$return[1],
							2=>$return[2],
							3=>$return[3],
							4=>$return[4],
							5=>$return[5],
							'data'=>$return['data'],
							'data_len'=>$return['data_len'],
							'data_php'=>$tmp[$i]
						);
					$return=$r;
					unset($tmp,$r);
				}else
					$return=explode(',',$return);
			}
		}
		return($return);
	}
	function set($path,$value=''){
		// set and value to path checking before if path is readonly or not
		$path=trim($path);	// trim path
		$tmp	=explode('/',$path);$c=count($tmp)-1;
		$type=false;
		if ($c>0){	// try to get information about structure, if file is readonly or not
			$variavel	=$tmp[$c];
			$ow		=$tmp[$c-1];
			unset($tmp);
			if (preg_match('/([0-9A-F]{2})[\.]{0,1}[0-9A-F]{12}/',$ow,$tmp)){
				$tmp=$tmp[1];
				if (!isset($OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel])){
					$tmp_v=@$this->get("/structure/$tmp/$variavel",OWNET_MSG_READ,false,false);	// get estrutucture information
					if ($tmp_v!==NULL){
						$tmp_v=explode(',',$tmp_v);
						$OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel]=$tmp_v;		// ok we will test it
						$type=$tmp_v;
					}
				}else
					$type=$OWNET_GLOBAL_CACHE_STRUCTURE[$tmp.'/'.$variavel];			// very fine, it was cached! :D performace boost
			}
		}
		if ($type!==false){
			if ($type[3]=='ro'){	// read only file
				trigger_error("Read only value set#1 [$path]",E_USER_NOTICE);
				return(false);	// return false on error
			}
		}
		unset($type,$tmp,$tmp_v,$variavel,$ow,$c);
	
		$this->disconnect();
		$this->connect();
		if (!$this->link_connected){
			trigger_error("Can't connect set#1",E_USER_NOTICE);
			return(false);		// return false on error
		}
		if (!is_string($value))
			$value=(string)$value;	// be sure that's an string
		$msg=$this->pack(OWNET_MSG_WRITE,strlen($path)+1+strlen($value)+1,strlen($value)+1);	// pack data
		if ( $this->send_msg($msg)===false ){
			trigger_error("Can't write to resource set#1",E_USER_NOTICE);
			return(false);	// error sending
		}
		if ( $this->send_msg($path.chr(0).$value.chr(0))===false ){
			trigger_error("Can't write to resource set#2",E_USER_NOTICE);
			return(false);	// error sending value
		}

		$data='';$tmp_ret='';
		$start=microtime(1);	// start timeout counter
		while(1){
			$tmp_ret=$this->get_msg(24);
			if ($tmp_ret===false){
				trigger_error("Can't read from resource set#1",E_USER_NOTICE);
				$this->disconnect();
				return(false);	// error reading return
			}
			if (strlen($tmp_ret)>0)	$start=microtime(1);
			$data.=$tmp_ret;unset($tmp_ret);
			if(strlen($data)>=24 || (microtime(1)-$start)>$this->timeout)	// timed out or got content
				break;
		}
		$ret=$this->unpack($data);	// unpack data return
		if (count($ret)<6){
			trigger_error("Error unpacking data set#1 [".strlen($data)."] ".$data,E_USER_NOTICE);
			$this->disconnect();
			return(false);		// return false on error
		}
		if (!isset($ret[2]))
			$ret[2]=1;		// be sure that we will work with error_reporting(E_ALL)
		if ($ret[2]!=0)
			$ret=false;		// return false on error
		$this->disconnect();		// disconnect from server
		if ($ret!==false)
			return(true);		// very fine :)
		return($ret);			// :( 
	}
	private function unpack($data){	// unpack returned contents (24 bytes data)
		$unpack=$this->unpack_ntohl($data);
		return($unpack);
		// version= 0, payload_len=1, ret_value=2, format_flags=3, data_len=4, offset=5
	}
	private function pack($function,$payload_len,$data_len){	// pack msg information (24 bytes)
		$pack=	$this->pack_htonl(0).
			$this->pack_htonl($payload_len).
			$this->pack_htonl($function).
			$this->pack_htonl(258).
			$this->pack_htonl($data_len).
			$this->pack_htonl(0);
		return($pack);
	}
}
/*
explanation:


EVERY FUNCTION TRIGGER AN ERROR! you should use @$ow->function to don't handle errors


$ow=new OWNet($host,$timeout=5,$use_swig_dir=true);
    in top of file we have some constants: (line 58)
        define('OWNET_DEFAULT_HOST'    ,'127.0.0.1');
        define('OWNET_DEFAULT_PORT'    ,4304);   
        i don't know what's the default OW port, i'm using today 4304 :)
    for OWNet($host) we can use this types of host value:
    "scheme://host:port" "scheme://host" "anything that can't be parsed with parseurl"
    if port isn't set we get default port, if host isn't set we get default host
    if scheme == "stream" or scheme == "ow-stream"
       we will prefer to use PHP stream_socket_client functions
       else if function socket_create exists we will use socket_connect() with sockets we can set TCP_NODELAY SO_REUSEADDR SO_OOBINLINE(we use it?)  SO_RCVBUF SO_SNDBUF
$ow->setHost($host)
    is the same thing that new OWNet($host)
$ow->getHost()
    get host URI
       owstream://host:port if using stream_socket_client
       ow://host:port if using sockets
$ow->setTimeout($timeout=5)
    set read timeout, default 5
$ow->getTimeout()
    get read timeout
$ow->set($path,$value='')
    set an value to path
    true on success
    false on error or if file is readonly
$ow->read($path,$parse_value=true)
	return value if parse_value return an php parsed value, if not return an string
$ow->dir($path)
	return an dir (see setUserSwigDir and OWNet constructor)
$ow->presence($path)
	get presence

$ow->get($path='/',$get_type=OWNET_MSG_READ_ANY,$return_full_info_array=false,$parse_php_type=true)
    on error return NULL
    get_type can be:
       OWNET_MSG_READ (execute OWNET_MSG_READ and if don't find execute OWNET_MSG_DIR)
       OWNET_MSG_READ *default
          read an file from owserver
       OWNET_MSG_DIR
          read an dir from owserver
       OWNET_MSG_PRESENCE
          read presence from owserver (return false or true)
    return_full_info_array
       if true return an array with everything that was received from owserver more data_php and unit if file is an temperature value
    parse_php_type
       try to check what type is an file (temperature, boolean, string, number (double or integer))

$ow->setUseSwigDir($use)	// use swig dir style (dir,dir,dir) and not php array (array(dir,dir,dir))
$ow->getUseSwigDir()		// get if using swig dir style


END :)

examples:

$ow=new OWNet("tcp://172.16.1.100:4304");
var_dump($ow->get("/",OWNET_MSG_DIR,true));
var_dump($ow->get("/10.E8C1C9000800/temperature",OWNET_MSG_READ,true));
var_dump($ow->get("/10.E8C1C9000800",OWNET_MSG_PRESENCE,true));
var_dump($ow->get("/WRONG VALUE",OWNET_MSG_PRESENCE,true));

var_dump($ow->get("/",OWNET_MSG_DIR,false));
var_dump($ow->get("/10.E8C1C9000800/temperature",OWNET_MSG_READ,false));
var_dump($ow->get("/10.E8C1C9000800",OWNET_MSG_PRESENCE,false));
var_dump($ow->get("/WRONG VALUE",OWNET_MSG_PRESENCE,false));


return:

array(9) {
  [0]=>  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(5)
    [5]=>    int(0)
    ["data"]=>    string(42) "bus.0athaðãaPÜa»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(5) "bus.0"
  }
  [1]=>  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(8)
    [5]=>    int(0)
    ["data"]=>    string(42) "settings0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(8) "settings"
  }
  [2]=>  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(6)
    [5]=>    int(0)
    ["data"]=>    string(42) "system0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(6) "system"
  }
  [3]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(10)
    [5]=>    int(0)
    ["data"]=>    string(42) "statistics0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(10) "statistics"
  }
  [4]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(16)
    [5]=>    int(0)
    ["data"]=>    string(42) "/10.E8C1C9000800P×aàÑa*»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(16) "/10.E8C1C9000800"
  }
  [5]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(16)
    [5]=>    int(0)
    ["data"]=>    string(42) "/10.54FDED000800P×aàÑa*»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(16) "/10.54FDED000800"
  }
  [6]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(16)
    [5]=>    int(0)
    ["data"]=>    string(42) "/10.6F7EC9000800P×aàÑa*»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(16) "/10.6F7EC9000800"
  }
  [7]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(16)
    [5]=>    int(0)
    ["data"]=>    string(42) "/28.924FE0000000P×aàÑa*»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(16) "/28.924FE0000000"
  }
  [8]=>
  array(9) {
    [0]=>    int(0)
    [1]=>    int(42)
    [2]=>    int(0)
    [3]=>    int(258)
    [4]=>    int(16)
    [5]=>    int(0)
    ["data"]=>    string(42) "/28.5D59E0000000P×aàÑa*»a0"
    ["data_len"]=>    int(42)
    ["data_php"]=>    string(16) "/28.5D59E0000000"
  }
}
array(10) {
  [0]=>  int(0)
  [1]=>  int(8192)
  [2]=>  int(12)
  [3]=>  int(0)
  [4]=>  int(12)
  [5]=>  int(0)
  ["data"]=>  string(12) "      28.625"
  ["data_len"]=>  int(12)
  ["data_php"]=>  float(28.625)
  ["unit"]=>  string(1) "C"
}
bool(true)
bool(false)
array(9) {
  [0]=>  string(5) "bus.0"
  [1]=>  string(8) "settings"
  [2]=>  string(6) "system"
  [3]=>  string(10) "statistics"
  [4]=>  string(16) "/10.E8C1C9000800"
  [5]=>  string(16) "/10.54FDED000800"
  [6]=>  string(16) "/10.6F7EC9000800"
  [7]=>  string(16) "/28.924FE0000000"
  [8]=>  string(16) "/28.5D59E0000000"
}
float(28.625)
bool(true)

*/


gdb.zip (314 KB)

Hi,

ich hatte mit der 5.3 jetzt auch einen Absturz auf WINDOWS.

Der Minidump ist aber leer, das Log deutet nix an :banghead:

Ciao
HerbertF

Ich habe konkret seit dem 1.10. das Problem, das mit PIGPIO abstürzt und JPaepers Modul IPS2GPIO nicht mehr läuft. Gefühlt seit 1-2 Wochen dauert es teilweise extrem lange, bis ein Script ausgeführt wird - teilweise 4-5 Sekunden Verzögerung. Ob es mit der 5.2 zusammenhängt, kann ich nicht sagen.

Hallo Peter1984,

wenn Du IPS auf einem Raspberry betreibst, würde mich dein Speicher (Swap- und etc…) und
auch die aktuell laufenden Programme interressieren. Kannst Du mit

sudo top
anschauen.
STRG+C bricht TOP ab. Komfortabler ist HTOP musst Du aber installieren :slight_smile:

Ich hatte mit PiGPIO einen Effekt, das per EXEC eine RPi Abfrage unendlich oft gestartet wurde.
Dadurch lief der SPeicher zu und der Pi schneckte nur noch bis zum endgüliten stillstand.
Im LOG steht dann nix davon (Endet im nichts)… :mad:

Magst Du mal schauen ?

Liebe Grüße
lueralba

Habe jetzt auch das 5.2 Update gemacht, die ersten paar Tagen waren relaxt, jetzt wird die Zeit bis zum automatischen Neustart von meinem Watchdog , weil Symcon nicht mehr reagiert, immer kürzer. Heute ist es jetzt so schlimm das er stündlich neu startet. Einer nen Tipp was man machen kann?

Version 5.2 Revision: beadf93761da

Hi, ich habe den Raspi gerade mal komplett runtergefahren und stromlos gemacht. Hat wie erwartet auch nichts gebracht.
Hier die Ergebnisse von Top, allerdings direkt nach dem Neustart (PIGPIO war gerade aktiv, ist kurz drauf aber wieder abgeschmiert).


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  387 root      20   0 1072096 526768  14560 S  72,2 55,5 240:19.00 symcon

seit dem Update frisst Symcon immer ~50% des Speicher
CPU schwankt von 2-3% bis Volllast…

Auch bei mir, der Speicher läuft langsam aber sicher voll:

@Peter1984: Schau mal hier: Help! Linux ate my RAM! Du musst die Zahlen die bei Buffer drin stehen ebenfalls mit einrechnen. Somit hast du aktuell eine Menge frei.

paresy

Ok, nichts desto trotz habe ich die extremen Latenzen, bis ein Skript ausgeführt wird, und eben IPS2GPIO (PIGPIO) läuft nicht mehr.

@Peter1984

Dein Speicher sieht besser als meiner aus:D

Magst/kannst du das Modul PiGPIO mal für einen Testzeitraum abschalten ggf. deinstallieren.
Vllt. bringt das Erkenntnisse wo wir weiter suchen können :frowning:

Das hatte ich mal aus verzweiflung gemacht, wie schon geschrieben, danach war erstmal Ruhe.
Hatte es aber auch nur getestet.

lueralba

Ja, kann ich machen. Kann ich die Variablen und die Instanzen irgendwo sichern, oder muss ich das alles neu anlegen (weil das Modul drauf referenziert und die Variablen in Skripten verwendet werden…)?

Ich meine dass die Variablen erhalten bleiben wenn Du Module löscht und neu installierst.
Kann ja paresy oder die Modulprogrammierer mal etwas zu sagen, damit hier nix „schief“ geht.

Grüße
lueralba

Guten Abend zusammen,

hatte gerade meinen dritten Absturz innerhalb einer Woche, identisches Fehlerbild wie von mir oben schon beschrieben.
Ich gehe jetzt mal auf die aktuelle Beta und schaue, ob sich dann was ändert.

Gruß
Georg