1

I'm quite new to python.

I'm writing an application that publishes JSON packets on a mosquito broker. The application spawns also a thread that subscribes to another topic of the broker and depending on the received message it has to start or stop a bash script.

def on_message(client, userdata, msg):
    if (str(msg.payload)=="START_1"):
        proc=subprocess.Popen("./rec", shell=True)
    elif(str(msg.payload)=="START_2"):
    proc=subprocess.Popen("./send", shell=True)
    elif(str(msg.payload)=="STOP_1"):
    subprocess.Popen("kill", "-9", "$proc.pid", shell=True)
    elif(str(msg.payload)=="STOP_2"):
        subprocess.call("kill", "-9", "$proc.pid", shell=True)

class FW_video (Thread):
   def __init__(self, nome):
      import paho.mqtt.client as mqtt
      from threading import Thread
      import time
      import json
      import random
      import sys
      import threading 
      import ctypes
      import subprocess
      Thread.__init__(self)
      self.nome = nome
   def run(self):
      print ("Thread '" + self.name + "' avviato")
      client=mqtt.Client()
      client.username_pw_set(username="--------", password="----------")
      client.connect("127.0.0.1",1883)
      client.subscribe("prova")
      client.on_message=on_message
      client.loop_forever()
      client.disconnect()
      print ("Thread '" + self.nome + "' terminato")




thread1 = FW_video("Thread#1")
thread1.start()

The bash script starts correctly but it doesn't stop when receives one of the two string (STOP_1 or STOP_2 )

Could someone, please, give me a hint. Thank you in advance

Ahsan Ali
  • 124
  • 8
  • You don't need to run the external `kill` command -- Python can signal processes right from the standard library using `os.kill()`. – Charles Duffy Jan 15 '20 at 14:14
  • 1
    And you *especially* don't need to do it for `Popen` instances, since they have [the `send_signal` method](https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal). – Charles Duffy Jan 15 '20 at 14:15
  • (And using `SIGKILL` instead of `SIGTERM` unless you have a really good reason is a Very Bad Idea, as it doesn't let a program's output it's started writing get flushed, so it's an easy way to corrupt data). – Charles Duffy Jan 15 '20 at 14:15
  • ...and, well, nothing here is replacing `$proc.pid` with the actual PID. – Charles Duffy Jan 15 '20 at 14:16
  • Thank you for your answer @CharlesDuffy! I replaced 'subprocess.Popen("kill", "-9", "$proc.pid", shell=True)' with 'os.kill(proc.pid, signal.SIGTERM)' but it still doesn't work. To be more precise (if can help to find a solution) the two bash script that I try to start and stop are two gstreamer pipeline, one to send a video and the other to receive it. – Ohitekah Wanageeska Jan 15 '20 at 17:17
  • First -- don't use `shell=True` unless you have a very specific and compelling reason to; it adds a bunch of unwelcome complexities. Second -- unless there's a reason to do otherwise (like needing your shell script to be able to do shutdown/cleanup afterwards), make sure your `rec` and `send` scripts `exec` gstreamer so that the copy of gstreamer inherits the same PID, instead of having a child process that's a shell with one PID that Python knows, and a grandchild of that that's gstreamer, with a different PID that Python *doesn't* know. – Charles Duffy Jan 15 '20 at 17:26
  • ...if you *can't* `exec` gstreamer from the shell, then you want to make the scripts know how to kill their children when they're shut down. That's very doable, but really a topic for a separate shell-scripting question rather than a Python one. (Moreover, that question has already been asked and answered; let me try to find some links). – Charles Duffy Jan 15 '20 at 17:28
  • ...okay, https://stackoverflow.com/questions/12856620/how-to-handle-signals-in-bash-during-synchronous-execution is one question that has some good answers on how to make your bash scripts properly shut down their children -- but only do that if you can't just make the bash scripts *replace themselves with* those children via `exec`, and thus not remain in memory at all after gstreamer is started. And again, if you don't want an extra shell in the process table that signals need to be propagated through, also stop using `shell=True`. – Charles Duffy Jan 15 '20 at 17:30

0 Answers0