Properly exiting a GladeVCP panel embedded in Axis
- tnl.lambert
- Offline
- Junior Member
Less
More
- Posts: 37
- Thank you received: 1
09 Jan 2015 06:10 - 09 Jan 2015 06:11 #54809
by tnl.lambert
Properly exiting a GladeVCP panel embedded in Axis was created by tnl.lambert
I'm working with a GladeVCP panel embedded in axis - same project as my last thread. I've successfully implemented a modbus protocol in a background python thread that talks over USB to a serial port.
When I close the axis window, several errors are thrown:
I think that what is happening is that the thread is staying alive after the window is closed. The 'quit with close' line in the above text is where my gtk exit handler is called, but it looks like the first error occurs before that. Or maybe I'm missing something - perhaps I need a custom shutdown script? Any info would be appreciated.
When I close the axis window, several errors are thrown:
Starting LinuxCNC...
INFO CLASSICLADDER- No ladder GUI requested-Realtime runs till HAL closes.
INFO CLASSICLADDER---I/O modbus master closed!
INFO CLASSICLADDER---I/O modbus master (Ethernet) init ok !
Exiting Main Thread
Starting Modbus-Thread-1
Start Time: 1420754623.674504
Xlib.protocol.request.QueryExtension
Xlib.protocol.request.QueryExtension
/usr/bin/gladevcp:292: GtkWarning: GdkWindow 0x3400003 unexpectedly destroyed
gtk.main()
quit with close
**** GLADE VCP ERROR: X Protocol Error: 3
Shutting down and cleaning up LinuxCNC...
Running HAL shutdown script
ULAPI: WARNING: module 'HAL_classicladder' failed to delete shmem 03
ERROR CLASSICLADDER- Error intializing classicladder user module.
ERROR: Can't remove RTAI modules, kill the following process(es) first
USER PID ACCESS COMMAND
/dev/rtai_shm: stan 1548 ....m gladevcp
I think that what is happening is that the thread is staying alive after the window is closed. The 'quit with close' line in the above text is where my gtk exit handler is called, but it looks like the first error occurs before that. Or maybe I'm missing something - perhaps I need a custom shutdown script? Any info would be appreciated.
Last edit: 09 Jan 2015 06:11 by tnl.lambert.
Please Log in or Create an account to join the conversation.
09 Jan 2015 19:33 #54818
by andypugh
If you do have a shutdown script then you can have your GladeVCP panels save state on exit (the GladeVCP docs explain how to do this). So it is probably worth trying this anyway.
Replied by andypugh on topic Properly exiting a GladeVCP panel embedded in Axis
perhaps I need a custom shutdown script? Any info would be appreciated.
If you do have a shutdown script then you can have your GladeVCP panels save state on exit (the GladeVCP docs explain how to do this). So it is probably worth trying this anyway.
Please Log in or Create an account to join the conversation.
- tnl.lambert
- Offline
- Junior Member
Less
More
- Posts: 37
- Thank you received: 1
10 Jan 2015 00:43 - 10 Jan 2015 00:46 #54828
by tnl.lambert
Replied by tnl.lambert on topic Properly exiting a GladeVCP panel embedded in Axis
I have tried adding the on_unix_signal handler, and I've tried saving state - I think that the problem is tied to the fact that the gladevcp process sticks around after axis closes (and after the error messages are printed).
I have a destroy handler that calls gtk.main_exit(), but maybe it's just a matter of my threads failing to terminate? I have also looked through the forums, specifically this one: forum
I've attached my code if you don't mind taking a look:
I have a destroy handler that calls gtk.main_exit(), but maybe it's just a matter of my threads failing to terminate? I have also looked through the forums, specifically this one: forum
I've attached my code if you don't mind taking a look:
#!/usr/bin/env python
import hal
import gtk
import gobject
import glib
import linuxcnc
import serial
import threading
import sys
import time
numerr = 0;
h = hal.component("IRB")
h.newpin("go", hal.HAL_BIT, hal.HAL_IN)
h.ready()
mainclosed = 0
try:
s = linuxcnc.stat() # create a connection to the status channel
s.poll() # get current values
except linuxcnc.error, detail:
print "LINUXCNC error", detail
gtk.main_quit()
sys.exit(1)
#for x in dir(s):
# if not x.startswith('_'):
# print x, getattr(s,x)
class myThread (threading.Thread):
def __init__(self, threadID, name, timeout):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.timeout = timeout
def run(self):
print "Starting " + self.name
modbusInit(self.name, self.timeout)
print "Exiting " + self.name
def modbusInit(threadName,timeoutIn):
ser = serial.Serial('/dev/ttyUSB0',timeout = timeoutIn)
outputByte = 165
numerr = 0
inSize = 1
#calcXor()
print "Start Time: %f" % time.time()
while numerr < 100:
if mainclosed == 1:
print "Thread Closing"
thread.exit()
if h.go == 1:
print "working thread 1: %f" % time.time()
#try:
if sendFc16(165,1,2,[102,122],ser) == 1:
print "Communication Success"
#time.sleep(1)
#outCRC = getCRC(outputByte)
#if writeByte(chr(outputByte),ser) == 1:
#print "inside if"
#writeByte(chr(65),ser)
#writeByte(chr(5),ser)
#print "written"
#time.sleep(0.5)
#inputByte = readByte(inSize,ser)
#print "direct input =" + inputByte
#print "inputByte = %d" % ord(inputByte)
#outputByte += 1
#except:
# print "Comm Error"
#checkCRC()
ser.close()
#def calcXor():
# print 'Writing File'
# f = open('xortable', 'w')
# f.write('[')
# for i in range(0,256):
# f.write('[')
# for j in range(0,255):
# f.write(str(i ^ j) + ',')
# f.write(str(i ^ 255) + '],')
# f.write('];')
# f.close
def writeByte(outByte,outPort):
#outPort.flushInput()
#outPort.flushOutput()
return outPort.write(outByte)
def readByte(readSize,readPort):
inputByte = readPort.read(readSize)
while len(inputByte)==0:
inputByte = readPort.read(readSize)
return inputByte
def getCRC(outMessage):
CRCFull = 0xFFFF
#0xFFFF;
CRC = bytearray(2);
for i in range(0,len(outMessage)-2):
CRCFull = CRCFull ^ outMessage[i]
#print "CRCFull1 =" + bin(CRCFull) + "i = %d" % i
#CRCFull = CRCFull % 2**16
for j in range(0,8):
CRCLSB = CRCFull & 0x0001
CRCFull = (CRCFull >> 1) & 0x7FFF
#0x7FFF
#print "CRCFull2 =" + bin(CRCFull) + "CRCLSB = %d" % CRCLSB
#CRCFull = CRCFull % 2**16
if CRCLSB==1:
CRCFull = CRCFull ^ 0xA001
#0xA001
#print "CRCFull3 =" + bin(CRCFull)
#CRCFull = CRCFull % 2**16
CRC[1] = (CRCFull >> 8) & 0xFF
CRC[0] = CRCFull & 0xFF
return CRC
def buildMessage(address,type,start,registers,message):
message[0] = address
message[1] = type
message[2] = start >> 8
message[3] = start
message[4] = registers >> 8
message[5] = registers
outputCRC = getCRC(message)
#print "mess0 is: %d" % message[0]
#print "mess1 is: %d" % message[1]
#print "mess2 is: %d" % message[2]
#print "mess3 is: %d" % message[3]
#print "mess4 is: %d" % message[4]
#print "mess5 is: %d" % message[5]
#print "mess6 is: %d" % message[6]
#print "mess7 is: %d" % message[7]
#print "mess8 is: %d" % message[8]
#print "mess9 is: %d" % message[9]
#print "mess10 is: %d" % message[10]
message[len(message)-2] = outputCRC[0]
message[len(message)-1] = outputCRC[1]
print "CRC0 is: %d" % message[11]
print "CRC1 is: %d" % message[12]
def sendFc16(address,start,registers,values,port):
if port.isOpen():
port.flushInput()
port.flushOutput()
message = bytearray(9 + 2 * registers)
response = bytearray(8)
message[6] = registers * 2
for i in range(0,registers):
message[7 + 2*i] = values[i] >> 8
message[8 + 2*i] = values[i]
#print "i = %d" % i
buildMessage(address,16,start,registers,message)
#print "message length = %d" % len(message)
writeMessage(port,message)
#print "Message Written"
response = getResponse(port)
#print "res7 is: %d" % response[7]
#print "After Response"
if checkResponse(response):
print "CRC Match"
return 1
return 0
def writeMessage(port,message):
for i in range(0,len(message)):
writeByte(chr(message[i]),port)
#print "chrmess " + chr(message[i])
#print "Write Complete"
def getResponse(port):
response = bytearray(8)
for i in range(0,8):
#print "Before Read"
response[i] = readByte(1,port)
#print "resi is: %d" % response[i]
return response
def checkResponse(response):
CRC = getCRC(response)
#print "crc0 is: %d" % CRC[0]
return CRC[0] == response[len(response) - 2] and CRC[1] == response[len(response) - 1]
class HandlerClass:
def __init__(self,halcomp,builder,useropts):
filename = "/home/stan/Documents/gladetests/test1.ui"
builder = gtk.Builder()
builder.add_from_file(filename)
builder.connect_signals(self)
def on_hal_table1_destroy(self, widget, data=None):
print "quit with close"
mainclosed = 1
#self.halcomp.exit()
gtk.main_quit()
return False
def on_unix_signal(self,signum,stack_frame):
print "on_unix_signal(): signal %d received, saving state" % (signum)
self.ini.save_state(self)
gtk.main_quit()
self.halcomp.exit()
def on_hal_led1_hal_pin_changed(self,hal_led1,data=None):
n = 0
#while True:
#ser = serial.Serial('/dev/ttyUSB0')
#ser.open()
#ser.write('1')
#print ser.read(2)
#ser.close()
def on_hal_button1_pressed(self,hal_button1,data=None):
#n = 0
#print "%f" % n
#nhits += 1
#hal_label1.set_label("hits: %d" % nhits)
hal_button1.set_label("aha!")
#ser = serial.Serial('/dev/ttyUSB0')
#ser.open()
#while ser.read(1):
# ser.write('1')
#ser.close()
#ser = serial.Serial('/dev/ttyUSB0')
#ser.open()
#ser.write('ACK')
#print ser.read(2)
#n = ser.read(2)
#print n
#if n == 5:
# ser.write('ACK')
# print ser.read(13)
#ser.close()
def get_handlers(halcomp,builder,useropts):
for cmd in useropts:
exec cmd in globals()
return [HandlerClass(halcomp,builder,useropts)]
thread1 = myThread(1,"Modbus-Thread-1",0.5)
#thread1.daemon = True;
thread1.start()
if __name__ == "__main__":
main = main()
gtk.main()
print "Exiting Main Thread"
Last edit: 10 Jan 2015 00:46 by tnl.lambert.
Please Log in or Create an account to join the conversation.
10 Jan 2015 09:55 #54851
by cmorley
Replied by cmorley on topic Properly exiting a GladeVCP panel embedded in Axis
The gladevcp error is typical and nothing to worry about. caused by the remapped window (embedded glade panel).
You have loaded classicladder with modbus turned on.
Are you using classicladder with modbus?
Looks like the classicladder realtime module ends before the userland program, causing an error message.
Also I think typical and nothing to worry about.
Chris M
You have loaded classicladder with modbus turned on.
Are you using classicladder with modbus?
Looks like the classicladder realtime module ends before the userland program, causing an error message.
Also I think typical and nothing to worry about.
Chris M
Please Log in or Create an account to join the conversation.
- tnl.lambert
- Offline
- Junior Member
Less
More
- Posts: 37
- Thank you received: 1
12 Jan 2015 23:25 #54939
by tnl.lambert
Replied by tnl.lambert on topic Properly exiting a GladeVCP panel embedded in Axis
If both of those errors are typical - how do I fix the GdkWindow warning? And what is keeping the gladevcp process open?
I am currently killing the process in order to stop it, which isn't really a solution. My feeling is that it stems from either the multithreading or the exit handler - but no progress so far. I just need it to terminate fully.
I am currently killing the process in order to stop it, which isn't really a solution. My feeling is that it stems from either the multithreading or the exit handler - but no progress so far. I just need it to terminate fully.
Please Log in or Create an account to join the conversation.
13 Jan 2015 05:03 #54945
by cmorley
Replied by cmorley on topic Properly exiting a GladeVCP panel embedded in Axis
Why do you care about the warning?
Is there an actual problem or do you just not like the error message?
Is there an actual problem or do you just not like the error message?
Please Log in or Create an account to join the conversation.
13 Jan 2015 05:13 #54947
by cmorley
Replied by cmorley on topic Properly exiting a GladeVCP panel embedded in Axis
The GDK warning is also because of the gladevcp embedded window.
Please Log in or Create an account to join the conversation.
- tnl.lambert
- Offline
- Junior Member
Less
More
- Posts: 37
- Thank you received: 1
21 Jan 2015 23:23 #55240
by tnl.lambert
Replied by tnl.lambert on topic Properly exiting a GladeVCP panel embedded in Axis
Yes, there is an actual problem. I'm still avoiding having to deal with it by terminating the process through the 'System Monitor' tool.
I need to understand how the GladeVCP embedded window is terminated when the axis GUI is closed. The essential problem is that unless I make my thread a daemon thread, it won't exit when axis does. Thus, gladevcp runs in the background until I kill it from the System Monitor. I've tried several methods, but none of them have succeeded (the daemon thread method causes several new problems too).
Should I use a signal handler? A join() function? What information does axis pass to GladeVCP when it closes? And what is the proper way for me to end a thread using a GladeVCP signal?
I need axis to tell GladeVCP to stop, so that I can stop my thread at an appropriate point.
Thanks!
I need to understand how the GladeVCP embedded window is terminated when the axis GUI is closed. The essential problem is that unless I make my thread a daemon thread, it won't exit when axis does. Thus, gladevcp runs in the background until I kill it from the System Monitor. I've tried several methods, but none of them have succeeded (the daemon thread method causes several new problems too).
Should I use a signal handler? A join() function? What information does axis pass to GladeVCP when it closes? And what is the proper way for me to end a thread using a GladeVCP signal?
I need axis to tell GladeVCP to stop, so that I can stop my thread at an appropriate point.
Thanks!
Please Log in or Create an account to join the conversation.
22 Jan 2015 02:27 - 22 Jan 2015 02:29 #55248
by newbynobi
Replied by newbynobi on topic Properly exiting a GladeVCP panel embedded in Axis
Hallo,
within the application that call the dynamic tab, you will have to check the socket and remember it. When the main application finish, you have to check if there are still clients open and send to all of them a close terminate signal.
Please check the gmoccapy.py code (~/linuxcnc-dev/src/usr-intf/gmoccapy/gmoccapy.py) from line 919 to line 965 for details.
Normally that is done by axis, gscreen and gmoccapy by default.
Norbert
within the application that call the dynamic tab, you will have to check the socket and remember it. When the main application finish, you have to check if there are still clients open and send to all of them a close terminate signal.
Please check the gmoccapy.py code (~/linuxcnc-dev/src/usr-intf/gmoccapy/gmoccapy.py) from line 919 to line 965 for details.
# =============================================================
# Dynamic tabs handling Start
def _init_dynamic_tabs( self ):
# dynamic tabs setup
self._dynamic_childs = {}
# register all tabs, so they will be closed together with the GUI
atexit.register( self._kill_dynamic_childs )
tab_names, tab_location, tab_cmd = self.get_ini_info.get_embedded_tabs()
if not tab_names:
print ( _( "**** GMOCCAPY INFO ****" ) )
print ( _( "**** Invalid embeded tab configuration ****" ) )
print ( _( "**** No tabs will be added! ****" ) )
return
try:
for t, c, name in zip( tab_names, tab_cmd, tab_location ):
nb = self.widgets[name]
xid = self._dynamic_tab( nb, t )
if not xid: continue
cmd = c.replace( '{XID}', str( xid ) )
child = subprocess.Popen( cmd.split() )
self._dynamic_childs[xid] = child
nb.show_all()
except:
print( _( "ERROR, trying to initialize the user tabs or panaels, check for typos" ) )
# adds the embedded object to a notebook tab or box
def _dynamic_tab( self, widget, text ):
s = gtk.Socket()
try:
widget.append_page( s, gtk.Label( " " + text + " " ) )
except:
try:
widget.pack_end( s, True, True, 0 )
except:
return None
return s.get_id()
# Gotta kill the embedded processes when gmoccapy closes
def _kill_dynamic_childs( self ):
for child in self._dynamic_childs.values():
child.terminate()
# Dynamic tabs handling End
# =============================================================
Normally that is done by axis, gscreen and gmoccapy by default.
Norbert
Last edit: 22 Jan 2015 02:29 by newbynobi.
Please Log in or Create an account to join the conversation.
- tnl.lambert
- Offline
- Junior Member
Less
More
- Posts: 37
- Thank you received: 1
22 Jan 2015 09:07 #55256
by tnl.lambert
Replied by tnl.lambert on topic Properly exiting a GladeVCP panel embedded in Axis
Norbert - Thanks for the reply!
Unfortunately, I'm not sure what you mean. I'm using an embedded window, not a tab, and I am not using gmoccapy. I think I just don't know how to pass the terminate signal to the exit handler. Are you suggesting that I need to modify the dynamic tab segment of Axis itself?
I am also encountering a semi-related problem with the startup procedure. When I call my .ini file, it calls toplevel.py, which imports several other modules, all of which have 'import hal, h = hal.component("component1")' or some variation thereof. The issue is that only the first imported file seems to be able to create new hal components - all other files drop errors saying that there are duplicate modules with the same name. With some simple print statements, I can see that each hal.component call is indeed being executed multiple times. Is there a good reason for this? Perhaps I have factored my code improperly?
Thanks.
Unfortunately, I'm not sure what you mean. I'm using an embedded window, not a tab, and I am not using gmoccapy. I think I just don't know how to pass the terminate signal to the exit handler. Are you suggesting that I need to modify the dynamic tab segment of Axis itself?
I am also encountering a semi-related problem with the startup procedure. When I call my .ini file, it calls toplevel.py, which imports several other modules, all of which have 'import hal, h = hal.component("component1")' or some variation thereof. The issue is that only the first imported file seems to be able to create new hal components - all other files drop errors saying that there are duplicate modules with the same name. With some simple print statements, I can see that each hal.component call is indeed being executed multiple times. Is there a good reason for this? Perhaps I have factored my code improperly?
Thanks.
Please Log in or Create an account to join the conversation.
Moderators: HansU
Time to create page: 0.092 seconds