runeven
Posts: 9
Joined: Mon May 25, 2015 11:07 am

Python "while True:" loop exits without error

Sat Jul 04, 2015 12:58 pm

Hi

I have a python script on my Pi that runs a "while true" loop, but after some time it exit the script without printing any error in the terminal. The time before the script exits varies between 10 minutes to 5 hours. I don't have any break statements in the loop.

My question is therefore, how should I debug this? Does python keep some log files that I should look into?

I don't if it is relevant but I ssh into my headless Pi when I run my python script.

Thank in advance

User avatar
B.Goode
Posts: 10356
Joined: Mon Sep 01, 2014 4:03 pm
Location: UK

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 1:28 pm

runeven wrote:Hi

I have a python script on my Pi that runs a "while true" loop, but after some time it exit the script without printing any error in the terminal. The time before the script exits varies between 10 minutes to 5 hours. I don't have any break statements in the loop.

My question is therefore, how should I debug this? Does python keep some log files that I should look into?

I don't if it is relevant but I ssh into my headless Pi when I run my python script.

Thank in advance
Python itself is just an interpreter running your script and does not have its own logs.

The underlying operating system keeps loads of logs: look in /var/log

I don't know the answer to this, but does Raspbian have any default per-process limits on cpu time or elapsed time that might be exceeded?

Might it help to output a status message - such as the output from uptime - to help narrow this down?

runeven
Posts: 9
Joined: Mon May 25, 2015 11:07 am

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 1:45 pm

Thanks B.Goode. Here is what I get when running the uptime command:

Code: Select all

pi@raspberrypi ~ $ uptime
 13:33:18 up 1 day,  5:33,  1 user,  load average: 0.16, 0.07, 0.06
In my /var/log is a lots of different logs. Which one to look into?

Code: Select all

pi@raspberrypi ~ $ ls /var/log
alternatives.log    debug.2.gz      kern.log.2.gz       syslog.1
alternatives.log.1  dmesg           lastlog             syslog.2.gz
apt                 dmesg.0         lpr.log             syslog.3.gz
auth.log            dmesg.1.gz      mail.err            syslog.4.gz
auth.log.1          dmesg.2.gz      mail.info           syslog.5.gz
auth.log.2.gz       dmesg.3.gz      mail.log            syslog.6.gz
bootstrap.log       dmesg.4.gz      mail.warn           syslog.7.gz
btmp                dpkg.log        messages            user.log
btmp.1              dpkg.log.1      messages.1          user.log.1
ConsoleKit          dpkg.log.2.gz   messages.2.gz       user.log.2.gz
daemon.log          faillog         news                wtmp
daemon.log.1        fontconfig.log  ntpstats            wtmp.1
daemon.log.2.gz     fsck            regen_ssh_keys.log
debug               kern.log        samba
debug.1             kern.log.1      syslog

User avatar
jojopi
Posts: 3274
Joined: Tue Oct 11, 2011 8:38 pm

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 2:08 pm

runeven wrote:I have a python script on my Pi that runs a "while true" loop, but after some time it exit the script without printing any error in the terminal.
Are you running the script with sudo? That will inhibit your shell's notification if Python receives a fatal signal. After the script exits try:

Code: Select all

echo $?
A result greater than 128 means that Python was killed.

Other than external influences, the only real possibilities are logic errors, or bugs provoked within Python. Can you post a minimal script that demonstrates the problem?

Joe Schmoe
Posts: 4277
Joined: Sun Jan 15, 2012 1:11 pm

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 2:12 pm

This thread just goes to show that nothing lasts forever - not even "while true" loops.

Keep in mind that truth does change over time - many things that were accepted as true in the past no longer are. That could affect your "while true" loops.
And some folks need to stop being fanboys and see the forest behind the trees.

(One of the best lines I've seen on this board lately)

runeven
Posts: 9
Joined: Mon May 25, 2015 11:07 am

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 2:37 pm

jojopi wrote:Are you running the script with sudo? That will inhibit your shell's notification if Python receives a fatal signal. After the script exits try:

Code: Select all

echo $?
A result greater than 128 means that Python was killed.

Other than external influences, the only real possibilities are logic errors, or bugs provoked within Python. Can you post a minimal script that demonstrates the problem?
Thanks for your reply jojopi. Next time my script exits I will putting echo $? in the terminal. And yes I'm running it with sudo privileges.

My script control 2 pwm fans based on the temperature measured from three temperature sensors . I'm new to Python and Raspberry Pi so my script is based on/inspired by the following tutorials:
http://www.themakersworkbench.com/conte ... pm-arduino
https://www.cl.cam.ac.uk/projects/raspb ... mperature/

Code: Select all

import RPi.GPIO as GPIO
from time import sleep
from datetime import datetime

fan1PwmPin = 12
fan1RpmPin = 16
fan1Freqency = 0
fan1Rpm = 0

fan2PwmPin = 17
fan2RpmPin = 27
fan2Freqency = 0
fan2Rpm = 0

minPwmValue = 10
maxPwmValue = 90
pwmFrequency = 400

pwmValue = [0, 0]

minTemp = 25000  # Default: 25
maxTemp = 33000  # Default: 30

debugMode = True
counter = 0

sleepTime = 120

temostates = (1, "28-000006c4b900", "Living Room"), \
    (2, "28-000006c463a8", "Right"), \
    (3, "28-000006afc986", "Left")

GPIO.setmode(GPIO.BCM)

GPIO.setup(fan1PwmPin, GPIO.OUT)
GPIO.setup(fan2PwmPin, GPIO.OUT)

GPIO.setup(fan1RpmPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(fan2RpmPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)


fan1 = GPIO.PWM(fan1PwmPin, pwmFrequency)
fan2 = GPIO.PWM(fan2PwmPin, pwmFrequency)

fan1.start(0)
fan2.start(0)


def rpmFan1(channel):
    global fan1Freqency
    fan1Freqency += 1


def rpmFan2(channel):
    global fan2Freqency
    fan2Freqency += 1


def calculateRPM(frequency):
    rpm = frequency / 2 * 60
    return rpm


def mapPwmValueToTemperature(temperature):
    global minTemp, maxTemp, minPwmValue, maxPwmValue
    pwm = (temperature - minTemp) * (maxPwmValue - minPwmValue) \
        / (maxTemp - minTemp) + minPwmValue
    return pwm


def getTemperature(deviceId):
    # Open the file that we viewed earlier so that python can see what is in
    # it. Replace the serial number as before.
    tfile = open("/sys/bus/w1/devices/" + deviceId + "/w1_slave")
    # Read all of the text in the file.
    text = tfile.read()
    # Close the file now that the text has been read.
    tfile.close()
    # Split the text with new lines (\n) and select the second line.
    secondline = text.split("\n")[1]
    # Split the line into words, referring to the spaces, and select the 10th
    # word (counting from 0).
    temperaturedata = secondline.split(" ")[9]
    # The first two characters are "t=", so get rid of those and convert the
    # temperature from a string to a number.
    temperature = float(temperaturedata[2:])
    # Put the decimal point in the right place and display it.
    # temperature = temperature / 1000
    return temperature


while True:

    counter += 1

    # Getting the temperatures
    temperatureList = []
    printTemperature = ""
    i = 0

    for x in temostates:
        t = getTemperature(x[1])

        if i != 0:  # Omitting the first temperature measurement
            # Caluculating the fans" PWM-Value
            if t < minTemp:
                pwmValue[i-1] = 0
            elif (t >= minTemp) and (t <= maxTemp):
                pwmValue[i-1] = mapPwmValueToTemperature(t)
            else:
                pwmValue[i-1] = maxPwmValue

        temperatureList.append(t)
        printTemperature += x[2] + ": " + str(t / 1000) + " "
        i += 1

    fan1.ChangeDutyCycle(pwmValue[0])
    fan2.ChangeDutyCycle(pwmValue[1])

    sleep(20)  # Letting the fans get up to speed

    # Reading the fan 1's RPM
    fan1Freqency = 0
    GPIO.add_event_detect(fan1RpmPin, GPIO.RISING, callback=rpmFan1)
    sleep(1)
    GPIO.remove_event_detect(fan1RpmPin)

    fan1Rpm = calculateRPM(fan1Freqency)

    # Reading the fan 2's RPM
    fan2Freqency = 0
    GPIO.add_event_detect(fan2RpmPin, GPIO.RISING, callback=rpmFan2)
    sleep(1)
    GPIO.remove_event_detect(fan2RpmPin)

    fan2Rpm = calculateRPM(fan2Freqency)

    currentTimestamp = datetime.strftime(datetime.now(),
                                         "%Y-%m-%d %H:%M:%S")

    if debugMode:
        print(currentTimestamp)
        print printTemperature
        print("Fan 1 PWM: " + str(pwmValue[0]))
        print("Fan 1 RPM: " + str(fan1Rpm))
        print("Fan1 Hz: " + str(fan1Freqency))
        print("Fan 2 PWM: " + str(pwmValue[1]))
        print("Fan 2 RPM: " + str(fan2Rpm))
        print("Fan2 Hz: " + str(fan2Freqency))
        print("Loop Counter: " + str(counter))
        print("----------------------")
        sleepTime = 1

    sleep(sleepTime)

GPIO.cleanup()

User avatar
B.Goode
Posts: 10356
Joined: Mon Sep 01, 2014 4:03 pm
Location: UK

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 4:22 pm

I asked: "Might it help to output a status message - such as the output from uptime - to help narrow this down?"

Well, it seems that looking at your code that if debugMode is set to be True (which it is) then you should get a timestamp and a load of other information including the loop counter written to your terminal each time the While loop executes. So when the script exits you should still have the last debug message on the screen. Does examining that tell you anything? What happens if counter gets to be a larger number than Python can handle for example?
Last edited by B.Goode on Sat Jul 04, 2015 4:35 pm, edited 1 time in total.

runeven
Posts: 9
Joined: Mon May 25, 2015 11:07 am

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 4:31 pm

jojopi wrote:Are you running the script with sudo? That will inhibit your shell's notification if Python receives a fatal signal. After the script exits try:

Code: Select all

echo $?
A result greater than 128 means that Python was killed.
Now it exits again and here was what it returned:

Code: Select all

pi@raspberrypi ~ $ echo $?
139

User avatar
joan
Posts: 14959
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 4:50 pm

I'd hazard a guess it's down to the code continually calling add_event_detect followed by remove_event_detect.

It'll probably be more reliable if you just call add_event_detect once before the loop and never call remove_event_detect.

runeven
Posts: 9
Joined: Mon May 25, 2015 11:07 am

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 5:30 pm

B.Goode wrote: Well, it seems that looking at your code that if debugMode is set to be True (which it is) then you should get a timestamp and a load of other information including the loop counter written to your terminal each time the While loop executes. So when the script exits you should still have the last debug message on the screen. Does examining that tell you anything? What happens if counter gets to be a larger number than Python can handle for example?
B.Goode, it just output expected information and the counter only gets up to around 500, so I guess that it shouldn't be the problem?
joan wrote:I'd hazard a guess it's down to the code continually calling add_event_detect followed by remove_event_detect.

It'll probably be more reliable if you just call add_event_detect once before the loop and never call remove_event_detect.
Joan - you're properly right... I think I must look into how to calculate the fans RPM in another way...

Thanks for your replies.

User avatar
joan
Posts: 14959
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 5:36 pm

runeven wrote: ...
I think I must look into how to calculate the fans RPM in another way...
...
Your code should work as is by simply moving the add event detects before the while True and removing the remove event detect calls.

I doubt you'll notice any difference in load by having the event detects permanently enabled.

Joe Schmoe
Posts: 4277
Joined: Sun Jan 15, 2012 1:11 pm

Re: Python "while True:" loop exits without error

Sat Jul 04, 2015 5:56 pm

runeven wrote:
jojopi wrote:Are you running the script with sudo? That will inhibit your shell's notification if Python receives a fatal signal. After the script exits try:

Code: Select all

echo $?
A result greater than 128 means that Python was killed.
Now it exits again and here was what it returned:

Code: Select all

pi@raspberrypi ~ $ echo $?
139
139 is SIGSEGV
(You subtract 128, then look up the result [11] in /usr/include/arm-linux-gnueabihf/bits/signum.h)

Segmentation violation is general Unix-exe for trying to access memory you shouldn't be accessing. Whether this is due to a bug in your code or in the Python interpreter remains to be seen...

Anyway, these kinds of problems can be tricky to track down - generally because your program just silently exits and you're left scratching your head as to what happened and why. I had a similar issue recently where a program (Not written in Python and not written by me) was mysteriously exiting for no good reason after running for a while. I eventually figured it out by running it under gdb and telling gdb to tell me about any signals received (You'll have to look up the details in "man gdb"...) and that (eventually) told me where in the program it was receiving a bogus signal (In this case, SIGPIPE). I eventually fixed this by just ignoring SIGPIPE - since it wasn't my program, I didn't want to expend the effort to actually debug it.

Anyway, that's my suggestion to you - try running it under gdb and you should be able to figure out where it is SIGSEGV'ing.
And some folks need to stop being fanboys and see the forest behind the trees.

(One of the best lines I've seen on this board lately)

Return to “Troubleshooting”