RWAP
Posts: 14
Joined: Tue Aug 09, 2016 8:49 am

Best method of auto-running a C program

Mon Dec 11, 2017 11:50 am

We have developed a C program which we have (for a long time) launched whenever the Raspberry Pi starts up by running a shell script from etc/rc.local (say ./run.sh )

That worked fine, until we had to change the program to form two jobs which communicate using shared_mem.

Now, on launch from rc.local, it reports the error "cannot open shared memory for writing".

However, if you open a console prompt and enter the command ./run.sh; it launches both jobs without any issue, so I assume the issue is the point at which the shared_mem becomes available.

Does anyone have experience of this and how to overcome the issue?

User avatar
topguy
Posts: 4354
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Best method of auto-running a C program

Mon Dec 11, 2017 12:05 pm

Simplest possible solution.
- Spawn off "./run.sh" in background by adding "&" and then add a suitable "sleep x" at the start of the script.

Better solution.
- Still spawn off "run.sh" in the background but use a while loop to check for presence of "/dev/shm" maybe.
( assuming that the missing "/dev/shm" is the problem )

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Mon Dec 11, 2017 9:56 pm

RWAP,
That worked fine, until we had to change the program to form two jobs which communicate using shared_mem.
Might I ask why you did that?

It was a single process but now it is two. Sharing memory.

Why not just keep it as a single process with two threads internally that share memory.

Then you only have one program to launch, that in turn starts two threads.

This is easy to do with the pthreads library in C or just use std::thread or whatever it is called from C++.

My experience is that this whole memory shared between processes is more trouble than it's worth.

RWAP
Posts: 14
Joined: Tue Aug 09, 2016 8:49 am

Re: Best method of auto-running a C program

Mon Dec 11, 2017 10:22 pm

Heater wrote:
Mon Dec 11, 2017 9:56 pm
RWAP,
That worked fine, until we had to change the program to form two jobs which communicate using shared_mem.
Might I ask why you did that?

It was a single process but now it is two. Sharing memory.

Why not just keep it as a single process with two threads internally that share memory.

Then you only have one program to launch, that in turn starts two threads.

This is easy to do with the pthreads library in C or just use std::thread or whatever it is called from C++.

My experience is that this whole memory shared between processes is more trouble than it's worth.

The application reads data incoming via the GPIO block and then runs one of several conversion processes dependent on user defined settings.

We originally used a thread system, but for some reason found we kept losing some of the GPIO data and were not able to track down why this was happening.

By creating two completely independent tasks, where we could set the priority of the conversion process to -20, with the signals between the two tasks basically used to signify ONLY how much data has been read (and therefore being waited to be converted), we avoided this loss of GPIO data.

jahboater
Posts: 2519
Joined: Wed Feb 04, 2015 6:38 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 12:57 am

Heater wrote:
Mon Dec 11, 2017 9:56 pm
This is easy to do with the pthreads library in C or just use std::thread or whatever it is called from C++.
std::async now perhaps.
Heater wrote:
Mon Dec 11, 2017 9:56 pm
My experience is that this whole memory shared between processes is more trouble than it's worth.
Yes, I agree. I am sure there is a simpler way.

Why not just popen() the conversion processes?

asandford
Posts: 1990
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Best method of auto-running a C program

Tue Dec 12, 2017 2:22 am

Why not use something like MQTT as the message transport rather that shared memory?

User avatar
jcyr
Posts: 59
Joined: Sun Apr 23, 2017 1:31 pm
Location: Atlanta

Re: Best method of auto-running a C program

Tue Dec 12, 2017 4:27 am

Answering the OP question:

You could simply run both applications as daemons under systemd. Writing modern daemons is not the nightmare excercise writing a correct and complete traditional Unix daemon. A new style daemon for systemd is pretty much the same as a console app, with stdout and stderr automatically routed to the system log. Systemd takes care of most of the details for you!

Sytemd has options for making sure all subsystems you depend on are in place and running.

Good intro here https://access.redhat.com/documentation ... unit_files

Gory details here https://wiki.archlinux.org/index.php/systemd
If you want your child to get the best education possible, it is actually more important to get him assigned to a great teacher than to a great school. -- Bill Gates

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 5:02 am

RWAP,
The application reads data incoming via the GPIO block and then runs one of several conversion processes dependent on user defined settings.
OK. Sounds like a typical sort of thing to want to do.
We originally used a thread system, but for some reason found we kept losing some of the GPIO data and were not able to track down why this was happening.
So you had a race condition or something was blocking when it should not. This is easily avoidable using threads with mutexs and semaphores.

Plenty of examples around the net on how to do that with pthreads:
https://cs.gmu.edu/~rcarver/ModernMulti ... hreads.pdf
https://jlmedina123.wordpress.com/2013/ ... emaphores/

The same can be done in C++ with a higher layer of abstraction.
By creating two completely independent tasks, where we could set the priority of the conversion process to -20,
If you really have a thread that must run on time you can set the priority of a thread using pthreads as well:
http://www.yonch.com/tech/82-linux-thread-priority

Sounds like you have thrown out a perfectly good solution to replace it with someting more complex.

I'm with asandford on the MQTT suggestion. If you are going to separate the work into two processes that is a much nice way to go than trying to use shared memory.

In fact we did exactly that in one of our systems. We had two processes that we did not want linked together. One written in Pascal one in C++. They communicated through shared memory. Eventually we ripped that out and replaced it with communicating through MQTT. This made life a whole lot easier. And gave benefits like being able to run the processes on different machines, or easily add multiple instances of either process.

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 6:21 am

RWAP,

If you really want to stick with two processes and shared memory I think you should fix the root problem of "cannot open shared memory for writing" problem. Rather than mess around getting the processes started in the right order.

At least if the process cannot open for writing it should continue it's work and try again later.

When it comes to starting your processes at boot time use the modern way. A systemd service. As suggested above. I wrote some instructions on using systemd to start programs a while back: viewtopic.php?p=921354#p921354

Whilst we are here. Just a few days ago I tackled a similar problem:

Thread "A" needs to run quickly and never be slowed down or blocked. Among other things it produces data to be saved to file or database or whatever.

Thread "B" will take data from "A" and persist it to file or disk or whatever, it can block on file/network/database access.

My solution is simple. Thread "A" stuffs data into a queue. Thread "B" pulls data out of the "queue". Writing to my queue never blocks thread "A". When reading the queue thread "B" is blocked until data is available.

Here is the code with some comments added for explanation:

Header file:

Code: Select all

#include <string>
#include <thread>

#include "blockingconcurrentqueue.h"

// The structure of data items pushed from thread to thread.
struct Row {
  int source_id;
  std::string timestamp;
  int value;
};

// Feeder class has one method that runs as a separate thread
// and a method for other threads to queue data into it.
class Feeder {
public:
  Feeder();

  ~Feeder();

  // Push data to the thread.
  void feed(int source_id, std::string timestamp, int value);

  // The thread method.
  void thread(int tid);

private:
  std::thread t;
  bool run = true;

  // The magic concurrent queue
  moodycamel::BlockingConcurrentQueue<Row> q;
}; 
The c++ file:

Code: Select all

#include "Feeder.h"
#include "Persist.h"

// Constructor starts a thread running the thread method.
Feeder::Feeder() { t = std::thread(&Feeder::thread, this, 42); }

// Destructor tells the thread to stop then joins it.
Feeder::~Feeder() {
  run = false;
  t.join();
}

// Push data into the queue for the thread to consume. This never blocks.
void Feeder::feed(int source_id, string timestamp, int value) {
  Row row;
  row.source_id = source_id;
  row.timestamp = timestamp;
  row.value = value;
  q.enqueue(row);
}

// Thread method, waits for data on the queue and persists it to database.
void Feeder::thread(int tid) {
  Persist p;

  while (run) {
    Row row;

    // Wait for more data
    q.wait_dequeue(row);

    // Write data to database, can block a while.
    p.persist(row.source_id, row.timestamp, row.value);
  }
}
Note that the above does not use any mutex, locks or semaphores. The magic is the queue. That is not any old queue. It's a thread safe queue that is very fast as it also does not use any mutex, locks or semaphores. Magic!
https://github.com/cameron314/concurrentqueue
Last edited by Heater on Tue Dec 12, 2017 12:08 pm, edited 1 time in total.

jahboater
Posts: 2519
Joined: Wed Feb 04, 2015 6:38 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 10:18 am

Neat! I like it.

Still think you can use pipes to get free buffering and synchronization.

RWAP
Posts: 14
Joined: Tue Aug 09, 2016 8:49 am

Re: Best method of auto-running a C program

Tue Dec 12, 2017 10:23 am

Some great ideas :D

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 12:40 pm

jahboater,

Thanks.

Pipes would work fine. Except...

You need different code for pipes on Windows. This may not matter to our OP but I like write cross-platform code.

What happens when the pipe get's full? Doesn't that then block the GPIO producer process? I'm not sure.

Pipes only stream bytes from end to end. That means you have to package up your messages and decode them at the other end.

jahboater
Posts: 2519
Joined: Wed Feb 04, 2015 6:38 pm

Re: Best method of auto-running a C program

Tue Dec 12, 2017 1:06 pm

Heater wrote:
Tue Dec 12, 2017 12:40 pm
What happens when the pipe get's full? Doesn't that then block the GPIO producer process? I'm not sure.
You are quite right. The producer will get blocked automatically and transparently by the system when the queue (fifo) is full (64k on modern Linux I think) which is, I suspect, highly undesirable for something reading sensors via the GPIO! The pipe's file descriptor can be set O_NONBLOCK, but then the producer would have to implement its own buffering which is no help. The reader end can be set to O_ASYNC so it can get on with processing the data while it waits, and therefore more likely to be able to read stuff off the end of the queue.
But, I assume the queue in your C++ solution is limited only by available memory, much better.

There are also "message queues" which transport structured "messages" or packets.
but yes, they are not Windows friendly either.

User avatar
jcyr
Posts: 59
Joined: Sun Apr 23, 2017 1:31 pm
Location: Atlanta

Re: Best method of auto-running a C program

Tue Dec 12, 2017 11:04 pm

Not sure I understand the problem! Consider the following C code:

Code: Select all

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

int main()
{
        printf("Trying open\n");
        int fd = shm_open("/shared", O_RDWR | O_CREAT, S_IRWXU);
        if (fd >= 0)
                printf("Open ok\n");
        else
                printf("Open fail\n");
        while (1)
                sleep(1);
}
You can run any number of instances, in any order, all in parallel and the open will never fail. Nor is there any issue with race conditions as Linux pretty well guarantees the shm_operations are atomic.

Why was the OP's coding failing with an open failure in the first place?
If you want your child to get the best education possible, it is actually more important to get him assigned to a great teacher than to a great school. -- Bill Gates

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Wed Dec 13, 2017 7:01 am

jcyr,

I did not understand the problem either. That's why I suggested it's better to look into a fix for what he has rather than mess around getting the processes to start in the right order.

I suspect he is not using O_CREAT on both sides.

Heater
Posts: 8984
Joined: Tue Jul 17, 2012 3:02 pm

Re: Best method of auto-running a C program

Wed Dec 13, 2017 7:29 am

jahboater,

As you say the producer could do it's own buffering before feeding the pipe. Well, that is as easy as using a few lines of code like I showed above that starts a thread and creates an input queue for it. The thread would then then write to the pipe and get blocked if need be.

That queue, as I have used it above, will indeed eat all available memory if the consumer is dead. Convenient to use but ultimately catastrophic. Looking that the API again I see it has methods for avoiding that:

try_enqueue(item); // Fails if not enough memory to enqueue

The queue constructor takes a parameter that tells the size of queue to preallocate and will not exceed that.

Or you can check the approximate size of the queue as you go along.

size_approx();

Then we have a producer happily churning away twiddling it's GPIO without interruption and no overhead of kernel calls. After some point it's output data will be dropped if no one is listening.

RWAP
Posts: 14
Joined: Tue Aug 09, 2016 8:49 am

Re: Best method of auto-running a C program

Wed Dec 13, 2017 7:32 am

Heater wrote:
Wed Dec 13, 2017 7:01 am
jcyr,

I did not understand the problem either. That's why I suggested it's better to look into a fix for what he has rather than mess around getting the processes to start in the right order.

I suspect he is not using O_CREAT on both sides.
Ah - you are correct - I am not using O_CREAT for opening the shared memory on both parts of the program - I will update that and check if that resolves the issue! :oops:

Return to “General programming discussion”

Who is online

Users browsing this forum: No registered users and 3 guests