Jump to content

WxPython - aplicação crasha ao tentar parar uma thread...


Recommended Posts

Posted

Boas. Sou novo por estas bandas. Se me puderem dar uma ajudinha muito obrigado.

Estou a tentar fazer uma interface para um projecto da escola, mas deparei-me com o seguinte problema:

Estou a trabalhar com o GNU Radio, e tenho que capturar uns sinais e ao mesmo tempo mostrar uns gráficos em tempo real. A primeira parte do código e sintonizar o sinal e para isso preciso de usar um while. Para que a interface principal nao bloqueie tenho que correr essa parte numa thread a parte.

O que acontece é que quando tento parar por vezes obtenho este erro:

python: ../../src/xcb_lock.c:77: _XGetXCBBuffer: Assertion `((int) ((xcb_req) - (dpy->request)) >= 0)' failed.
Aborted

Isto acontece ainda mais frequentemente se fechar e correr o programa de novo.

É a primeira vez que faço algo deste género, não me admiro que seja qualquer coisa básica que me esteja a escapar.

Obrigado desde já pela ajuda que me possam dar.

O trecho de código com interesse é este abaixo:

#-----------------------------------------------------------------------#

class Tuner(wx.Frame):

def __init__(self, frame):
	wx.Frame.__init__(self, None, -1, "Tunning Stats")
	self.frame = frame
	self.Stop = False

def StartTune (self):

	#		Frame to display Tunning Evolution
	self.fftwindow = wx.Frame(self.frame,-1, "Tunning",
							style=wx.FRAME_FLOAT_ON_PARENT|wx.CAPTION|wx.CLOSE_BOX,
							pos=(200,170), size=(500,500))
	fftwindow = self.fftwindow

	# Create FFT Plot
	self.plot = wx.lib.plot.PlotCanvas(fftwindow, style=wx.RAISED_BORDER)
	size = fftwindow.GetClientSize()
	self.plot.SetInitialSize(size=size)
	self.plot.SetShowScrollbars(False)
	self.plot.SetEnableZoom(True)
	self.plot.SetFontSizeAxis(point=8)
	self.plot.SetFontSizeTitle(point=15)

	self.winSizer = wx.BoxSizer(wx.VERTICAL)
	self.winSizer.AddSpacer(20)
	self.winSizer.Add(self.plot)
	self.winSizer.AddSpacer(20)
	self.SetSizer(self.winSizer)
	fftwindow.Fit()
	fftwindow.Show()

	# Algum trabalho fictício ( o erro aparece tanto neste exemplo como com a captura de sinal )
	while(1):
		if self.Stop:
			time.sleep(2)       # não sei porque mas parece dar menos erros com o sleep aqui
			print "stop"
			return
		for i in range(100): print i
		for i in range(100): print 100-i


def StopTune(self):
	self.Stop = True

#---------------------------------------------------------------------------------------------#
#				GUI

(....)

#TUNNING INTERFACE

#		Prepare to Start Tunning
def OnTune(self,event):
	self.TuneButton.Enable(False)
	self.StopButton.Enable(True)
	self.SetStatusText("Tunning...")
	self.t = Tuner.Tuner(self)
	self.thread = threading.Thread(target=self.__run)
	self.thread.setDaemon(True)
	self.thread.start()

#		Start Tunnning
def __run(self):
	wx.CallAfter(self.AfterRun)
	self.t.StartTune()
	self.SetStatusText("Tunning Complete...")

#		Free GUI
def AfterRun(self):
	pass

#		Stop Tuner
def OnStop(self, event):
	self.t.StopTune()
	self.TuneButton.Enable(True)
	self.StopButton.Enable(False)
	print "Stoped!"

(.....)
Posted

Depois do OnStop fazes alguma coisa? Quando é que acontece o erro? É no momento que fazes o OnStop? É depois? Logo a seguir ou passado um tempo?

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Posted

São só dois botões. Start e Stop.

Para já, depois do OnStop simplesmente paro o ciclo. E se quiser recomeço a sintonizaçao no botão Start.

O erro acontece quanto forço a paragem. Estive a testar com um ciclo não infinito e corre bem se deixar ir até ao fim. Se tentar pará-lo a meio por vezes acontece o que expliquei.

Acho que tem que ver com a maneira como estou a tentar parar o ciclo. Já reparei que se fechar a janela principal, depois de ter iniciado e parado uma sintonização, a thread da GUI mantem-se na lista de processos. Se nunca tiver efectuado uma sintonização deixa de aparecer na lista como devia de ser.

Experimentei fazer kill ao terminar a GUI e resolve a parte do problema de quando reinicio o programa.

Mas a parte de forçar a paragem da sintonização continua a falhar.

Posted

Eu estava a ter esse problema com WxPython também não sei de é a melhor maneira ou a mais correcta mas funciona, mata todas as thread quando fechas o Gui, logo esse erro nao deve aparecer mais no init adiciona a linha 👍


def OnClose(self, a=None):
    os._exit(0)

def __init__():
    self.Bind(wx.EVT_CLOSE, self.OnClose)

RHCE - 120-062-534

Posted

Obrigado pela dica ao fechar a GUI.  👍

No final a sintonização vai ser feita de forma automática. Mas a seguir vem um processo de aquisição de dados que poderá correr ao longo de dias ou meses, sem interrupção. Só deve ser parado a pedido ou quando a luz vai abaixo 😉.

Por isso ainda tenho que por a funcionar a paragem forçada tanto da sintonização como da aquisição. ( Fazendo uma faz-se a outra )

Se me souberes dizer como parar o ciclo de sintonização/aquisição sem correr o risco do programa crashar ficava agradecido.

Posted

O erro acontece quanto forço a paragem. Estive a testar com um ciclo não infinito e corre bem se deixar ir até ao fim. Se tentar pará-lo a meio por vezes acontece o que expliquei.

Que queres dizer quando forças a paragem? É quando carregas no botão Stop?

Chega a executar isto: print "Stoped!" ?

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Posted

Sim. Imprime o "Stoped!".

No ciclo tenho esta verificação:

if self.Stop:

if fftwindow:

fftwindow.Destroy()

break

Passados uns segundos, provavelmente depois de correr a este pedaço de código, é que crasha e fecha GUI.

Posted

if self.Stop:

if fftwindow:

fftwindow.Destroy()

break

Onde é que está isso? Não encontro no pedaço de código que puseste originalmente.

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Posted

Onde é que está isso? Não encontro no pedaço de código que puseste originalmente.

# Algum trabalho fictício ( o erro aparece tanto neste exemplo como com a captura de sinal )

while(1):

    if self.Stop:

            time.sleep(2)      # não sei porque mas parece dar menos erros com o sleep aqui

            print "stop"

            return

    (....)

Está neste ciclo, mas como no final tenho uma janela criada, para além disso tenho o pedaço que mostrei para a fechar.

Posted

Podias mostrar o ciclo completo?

Estar a mostrar o ciclo aos retalhos não é muita boa ideia quando se tenta analisar o código.

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Posted

ve se não tens alguma chamada a janela depois de destruída......

isso provavelmente ia causar o erro 🙂

Parece que ja consegui resolver o problema.

O código para actualizar o gráfico estava na thread que tentava parar. E parece que mesmo depois de mandar parar ela ainda tentava redesenhar o gráfico depois dele ter sido destruido.

Alterei o programa de maneira a que a thread principal actualize o gráfico e a secundária apenas forneça os dados. E adicionei um pedaço de código para gerar um evento que avisa a principal que ja pode actualizar.

Agora deixou de dar erros ao cancelar. Obrigadão pela dica  😛

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.