ruby-mqtt icon indicating copy to clipboard operation
ruby-mqtt copied to clipboard

Graceful Termination

Open rlugge opened this issue 7 years ago • 9 comments

I've managed to work around most of the issues involved in using blocking code, but I've got a small annoyance left.

Because I need this as a long-running process running alongside a rails process, I need to be able to let it run in the background indefinitely, until a termination command is recieved.

So far, my best effort is to trap the Sigint signall and call client.disconnect(), but that simply throws a new error, since synchronize can't be called from trap context.

How am I supposed to trigger a graceful shutdown?

rlugge avatar Jun 09 '17 17:06 rlugge

Ah, I have not encountered this. I will look into how best to trap signals and trigger a clean disconnection.

Out of interest, what is the problem you are trying to work round?

  • Failing to get to more shutdown code?
  • Not causing the broker to deliver the Will message?
  • Error messages in log files?
  • Just trying to be clean and hygienic?

njh avatar Jun 09 '17 19:06 njh

A) Sigint will currently terminate the app in the middle of anything it is doing. This could lead to half-handled messages or similar issues. B) It generates a lot of garbage that gets output into the log.

So, basically the last two, but it's entirely possible that the first one will become an issue.

This may also be partially a workflow confusion. How do you normally terminate listening? With the MQTT code being blocking, it's kind of difficult for other code to run.

rlugge avatar Jun 09 '17 20:06 rlugge

It doesn't solve some of the underlying issues, but I actually realized I have a 'better' solution now:

client = MQTT::Client.new
client.host = '45.56.89.124'
# client.ssl = true
# client.cert_file = path_to('client.pem')
# client.key_file  = path_to('client.key')
# client.ca_file   = path_to('root-ca.pem')

running = true

trap("SIGINT") do
  running = false
end

Thread.new do
  begin
    $stdout.sync = true
    client.connect() do |client|
      topic = '/application/#'
      puts "Subscribing to: " + topic
      client.subscribe(topic)
      client.get do | topic, message |
        MQTTEventHandler.call(topic, message)
      end
    end
  rescue MQTT::ProtocolException => error
    puts "MQTT failure: " + error.message
  end
end

while(running)
  sleep 1
end

client.disconnect

Of course, from here I'm going to spend a lot of time cleaning up -- adding reconnect logic to automatically attempt a reconnect and so on.

rlugge avatar Jun 09 '17 20:06 rlugge

Hi, I have a ruby script that is working but continues to log a warning in my terminal even after the script has been terminated. This is the recurring message each time the MQTT client posts:

/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized

Any ideas?

teaching-innovation avatar Jul 28 '17 12:07 teaching-innovation

Could you post more about your code, @teaching-innovation ? Just the one line isn't helpful to me, though someone who maintains the gem may be able to get more out of it.

How are you running it, how are you terminating it, how are you using it, etc etc.

rlugge avatar Jul 28 '17 20:07 rlugge

Hi @rlugge thanks for the follow up: This is a bit of a summary of what I am trying to achieve: https://community.home-assistant.io/t/sound-monitoring-via-web-cam/24262

It works ok if I use nohup to run the script. But if I fun it without I continually get 581: warning seen bellow? Any ideas?

pi@raspberrypi:~ $ 
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:150: warning: method redefined; discarding old version=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:322: warning: method redefined; discarding old duplicate
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:327: warning: method redefined; discarding old duplicate=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:335: warning: method redefined; discarding old retain
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:340: warning: method redefined; discarding old retain=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:348: warning: method redefined; discarding old qos
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:353: warning: method redefined; discarding old qos=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:598: warning: method redefined; discarding old session_present
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:603: warning: method redefined; discarding old session_present=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:793: warning: method redefined; discarding old topics=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:882: warning: method redefined; discarding old return_codes=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/packet.rb:947: warning: method redefined; discarding old topics=
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized
/var/lib/gems/2.1.0/gems/mqtt-0.5.0/lib/mqtt/client.rb:581: warning: instance variable @last_packet_id not initialized

teaching-innovation avatar Aug 12 '17 22:08 teaching-innovation

Could you please format that a little cleaner? It's hard to read all jammed together on one line like that. Use triple backticks offset by line returns to make a code block.

rlugge avatar Aug 14 '17 15:08 rlugge

Hi @rlugge, I thought i did put it in a code block, but now that is has triple backticks it looks better.

teaching-innovation avatar Aug 15 '17 00:08 teaching-innovation

@teaching-innovation not really germane to this forum, but typically single backticks are used for small, inline code snippets, while the triple are used for larger code blocks, that's why you had formatting issues the first time -- it was the code format intended for inline use.

As for your issues... are you redefining methods? No clue what could be causing it, to be honest.

rlugge avatar Aug 15 '17 04:08 rlugge