-
Notifications
You must be signed in to change notification settings - Fork 418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multithreaded pwm at two pins -> pigpiod hangs up | Race condition? #357
Comments
Can you try to open just a single instance of pi and pass that object into your dimming method. I'm not sure that pi.stop() and pigpio.pi() are thread safe. |
Many thanks for your response. I tried your suggestion and it seems to work fine.
I tried another test: |
I would disagree with that statement but instead say the it is related to how the python module is instantiated. I'm not in a place to unzip and examine your code but I'll just say that pigpiod should handle multiple threads just fine. However, you need to be cautious of APIs that are not thread safe, such as |
I know that the python module runs the APIs atomically. I'll need to verify if the same can be said for pigpiod's socket handler. I thought I had run tests in the past with multiple clients hitting pigpiod without issue. I'll take a look at this over the next few days. |
@joan2937 , I'm not seeing a lock on |
@br-172 , on second examination of the code and thinking through the use case, pigpiod is not designed to allow multiple clients working simultaneously on the same host in a protected environment. Given the many APIs that have global side effects it would be impractical if not impossible to be "thread safe". Your best alternative is to use the python client, with the built-in atomic API execution and to protect against thread/API conflicts at the application layer. |
Many thanks for your effort. |
Sorry, I refer to the python module you have been using in your scripts as a client. It connects to pigpiod (server). |
I'm adding this comment to correct my earlier comments now that I have a better understanding of the behaviors between the original failing script and the edited working version. Hopefully this will help future readers of this issue. I said:
It was incorrect for me to assert that In the edited working script, only a single socket is open on pigpiod and this forces serial (or in other words, atomic) execution of the APIs called by the two worker threads. I never ran the Bottom line: APIs such as |
Thank you for your comments. Nevertheless, I tried to outline a workaround: The following is the idea described above with the proxy as a graphic. I know that sending strings and then evaluating them with job.split("_") is still not an optimal solution. But that's enough to test for now. Should I still leave the issue open? |
Why can't a single global instance of |
I don't know of a way to distribute a single global instance of I have combined related hardware into logical units. A script controls exactly one logical unit. Such a unit could e.g. a water supply, a video surveillance system or just a lamp. It is important that the actuators are not controlled sequentially, but at the same time. I tried to think of examples where you can see the design decision particularly well: My water supply consists of a pump, a tank, a temperature sensor on the pump motor against overheating and a water level sensor on the floor, if something should leak. I want to control a lamp in the kitchen. If I now install a lamp in the living room, I can copy the script kitchen_lamp.py and then call the copy livingroom_lamp.py. In this I only have to adjust the GPIO pin. Video surveillance is controlled by a script that controls the camera via "motion" and switches on a lamp via pigpio when motion is detected. The script also takes care of storing the camera images on the file system and sending alarm SMS. I call this script door_videoSurveillance.py. I found the clarity to be an advantage. Even if a script gets stuck due to a serious error, I can specifically end and restart this script based on its PID without the other scripts being affected. After implementing this concept, I found that after some time (hours to days) malfunctions occurred. The error occurred when two lamps were dimmed at the same time. Unfortunately, the error - apparently - was not reproducible. So I tried to narrow the problem down and designed a minimal example that still demonstrates the error. If I only want to use one global instance of |
I see. It sounds fairly complex. I find that having a lot of processes running come with their own baggage but I'm not in your situation. Good luck with it. I'm going to keep this open a bit longer to remind me. I haven't decided if it should be formally documented or just have a topic on the project wiki pages discussing it. |
@br-172 , I have a patch that will run the socket threads single threaded and it works on the test script you provided above (start of this issue). The patch is based on a In its current form, the patch has side affects that breaks other stuff - you can't run scripts on pigpiod for example. So it would have to be reworked quite a bit to make it into a release (if ever). But, on the other hand, it is so simple for your use case that it may be a better alternative than the architecture you describe above to work around the lack of multi-threading on the daemon. |
Hello,
this is according to my question here. In short:
The pin-state is 0. After the command
pi.write(pin, 1)
the pin-state is still 0. (unexpected)The connected LED flickers while changing the dutycycle. In detail, when dimming from 0 to 255, up to about 150 everything is fine, then the pin-status changes with a frequency of approx. 1 Hz. (abnormal)
In the meantime, I think I was able to isolate the problem. The problem occurs when two pins are dimmed at exactly the same time. Multithreading was used here to increase the probability of the error occurring.
The following script demonstrates it (using pigpiod (V71) with python3 on Raspberry Pi 3B+):
The Script produces the following output:
You can see, in this case the problem arose after 3 cycles (dimm-to-High and dimm-to-Low). Unfortunately that doesn't seem deterministic. To fix the problem pigpiod has to be restarted with
killall pigpiod
andpigpiod
. But after a few seconds it will be back.In my understanding pigpiod works with a pipe, so this behavior is not normal.
Can someone confirm the effect?
The text was updated successfully, but these errors were encountered: