I am creating a C program that is called from a shell script when a specific event is occurring. The C program gets an argument from the shell script like this:
> ./c-program.bin HELLO
Now the C program is running until it recieves a specific character as an argument. The problem is that if a second event occurs, and the C program is now called like this:
./c-program.bin WORLD
Then it is a new instance of the program that is started that knows nothing about the string from the first event. What i would like to achieve is something like this:
[EVENT0] ./c-program.bin HELLO
[EVENT1] ./c-program.bin WORLD
[EVENT2] ./c-program.bin *
c-program output:
HELLO WORLD
Any ideas on how to only have one instance of the program? The platform is Linux. The project is in its planning fase therefore, i do not have any specific code so far, i am trying to sort out the different problems first.
In outline, you have a magical "output everything" argument and want to accumulate all other arguments across multiple calls until you get the request to be magical? Easy enough, but requires some shared state. First hack would put that state in the filesystem (a database would be better, but is more complex).
I would use a pid file stored somewhere.
If you start the program, it should unsure that an other one is not running (using the pid file + verification). If not, create a named pipe where he would read data. Then put it in background, thanks to sub-process (fork) for instance.
Then an other instance is started, finding the pidfile and detecting that an instance is already launched. This second program would send argv[i] to the named pipe, so the first instance should print the data.
An other idea is to use a unix socket in a given file, like mysql.sock for instance.
Your program should check if another instance is running, and if that is the case pass its argument to that instance, and exit. The first instance to come alive should become the "server", that is stay alive ready to receive data. You can use shared memory or pipes for passing data between processes.
What you want isn't very clear. I think you are after a long-running process that accumulates "messages" of some sort, and then allows retrieval of those messages.
Here's one possible solution:
Try to create a fifo at a known location. If this succeeds, fork a daemon that listens on that fifo, accumulating messages until it receives a *, at which point it echos all messages back to the fifo, including the *.
The original process (whether it spawned a daemon or not) opens the fifo for writing, and pushes the message.
If the argument was *, it then reads the fifo and outputs everything it gets until it receives the echoed *.
You either need a intermediate app, or probably a separate shell script
The intermediate script would cache the parameters to disk until you pass a '*', at which point it then passes the entire cached string to the final c program.
So your first script would call the second script, passing:
secondscript HELLO
secondscript WORLD
secondscript *
When the second script receives a parameter of * it passes all the previous parameters to your c program
./c-program.bin HELLO WORLD
Compared to the later answers, this still seems by far the easiest option. You could script this in 10 minutes. Pseudocode for the intermediate app/script:
passedstring = args[0]
if passedstring = "*"
string cache = readcontents(cachefile)
call c program passing cache
clearcontents(cachefile)
else
append(cachefile, passedstring)
If however you want the challenge of developing a fancy dancin app that can check for another version of itself in memory, then pass stuff around in sockets, go for it :)
Related
My app is suppose to run long term (usually idling). If I try to open a second app (or trigger the app via global hotkey) I'd like my existing instance to receive some kind of IPC message and bring itself to the front. How do I do this on linux? The problem I've been running into is if I hold a global lock it doesn't automatically free when the instance close (usually I unlock it but an app can crash). If I try to use mkfifo I have no idea if I'm the first instance or not and every solution I can think of seems to require a lot of code and usually that's a sign to me I might be doing something wrong
There are many IPC primitives, all possible to use.
A simple one is using a named pipe: If the pipe doesn't exist then the program creates it and starts as usual. Then it polls the pipe at regular intervals to see if something can be received on the pipe, in which case the program receives it (and discards it) and puts itself to the "front".
If, on the other hand, the named pipe exists, then the program sends a simple dummy message through it, and exits.
I would use a flag file, e.g. /run/service-name/pid with PID of the first running instance. A new instance would check this file, if it does not exists, create it, if it does, send a SIGUSR1 to the PID in the file.
#Some programmer dude's answer above provides a bit more of flexibility.
Let's say that there is an existing program that listens on stdin for it's inputs. I want to create a pthread within the same program that is now the one to listen to stdin, and depending on what comes through, let it go through to the original program.
For this, I would create a pipe(), and configure the pthread to write to the input file descriptor, and the original program to listen to the output descriptor. Is this a correct way to have this done? I understand piping between processes, but is it possible to pipe like this within a single process?
Sure, you can use pipe(), but the data has to pass through the kernel even though both the end points are within the same process.
If you have source code for this (which I assume you have) and you don't mind making non-trivial changes, and performance is a priority for you, I would suggest using shared memory to send the data to the original program. It will be much faster than using pipe()
I´m trying to get some values displayed on an eInk-Display (via SPI). I already wrote the software to initialize the display and display the values passed as command-line arguments. The problem is, because of the eInk-technology it takes a few seconds for the display to have fully actualized, so the display-program is also running for this time.
The other ("Master"-) program collects the values and does other stuff. It has a main loop, which has to be cycled through at least 10x/second.
So I want to start the displaying program from within the main loop and immediately continue with the loop.
When using system() or execl(), the Master-program either waits till the display program is finished or exits into the new process.
Is there a way to just start other programs out of other ones without any further connection between them? It should run on Linux.
May fork() be a solution?
quick and dirty way: use system with a background suffix (&)
char cmd[200];
sprintf("%190s &","your_command");
system(cmd);
note that it's not portable because it depends on the underlying shell. For windows you would do:
sprintf("start %190s","your_command");
The main drawback of the quick & dirty solution is that it's "fire & forget". If the program fails to execute properly, you'll still have a 0 return code as long as the shell could launch the process.
A portable method (also allowing to take care of the return code of the process) is slightly more complex, involving running a system call from a thread or a forked executable. The quick & dirty solution does a fork + exec of a shell command behind the scenes.
I want to create a multithreaded application in C using pthreads. I want to have a number of worker threads doing stuff in the background, but every once in a while, they will have to print something to the terminal so I suppose they will have to
"acquire the output device" (in this case stdout)
write to it
release the output device
rinse and repeat.
Also, I want the user to be able to "reply" to the output. For the sake of simplicity, I'm going to assume that nothing new will be written to the terminal until the user gives an answer to a thread's output, so that new lines are only written after the user replies, etc. I have read up on waiting for user input on the terminal, and it seems that ncurses is the way to go for this.
However, now I have read that ncurses is not thread-safe, and I'm unsure how to proceed. I suppose I could wrap everything terminal-related with mutexes, but before I do that I'd like to know if there's a smarter and possibly more convenient way of going about this, maybe a solution with condition variables? I'm somewhat lost here, so any help is welcome.
Why not just have a thread whose job is to interact with the terminal?
If other threads want to send message or get replies from the terminal, they can create a structure reflecting that request, acquire a mutex, and add that structure to a linked list if structures. The terminal thread will walk the linked list, outputting data as needed and getting replies as needed.
You can use a condition variable to signal the terminal thread that there's now data that needs to be output. The structure in the linked list can include a response condition variable that the terminal thread can signal when it has the reply, if any.
For output that gets no reply, the terminal thread can delete the structure after it outputs its contents. For output that gets a reply, the terminal thread can signal the thread that's interested in the output and then let that thread delete the structure once it has copied the output.
You can use fprintf on terminal. fprintf takes care of the concurrency issues, like it will use mutex locks on stdout before writing to the output device.
In win32 programming in C:
Whats the best way to execute a win32 console program within another win32 program, and have the program that started the execution capture the output? At the moment I made the program redirect output to a file, but I am sure I must be able to open some sort of pipe?
Use the CreateProcess Win32 API to start the child process.
Pass to it a STARTUPINFO structure with hStdInput, hStdOutput and hStdError handles set to file handles you opened (either real files or memory mapped files should work). You don't need to specify all three, you can redirect only the ones you really need; most common case is hStdOutput.
If you want to communicate with the child process (through hStdInput), you need to wait for it to initialize by calling WaitForInputIdle.