I was trying to run netcat by using ssh and seems that my code always fails in my C code. Here are the commands which I am executing using system() in this order.
system("ssh machine 'nc -l 61001|dd bs=64M of=temp' &")
system("/bin/dd if=filename bs=64M|nc IP_address 61001")
I noticed that the first command works correctly as the temp file is created on the remote machine. The second dd command fails and states that 0 bytes has been written on the remote machine. These commands work correctly when executed from the terminal, but fail as soon as I put it in system() calls in C.
Short answer:
a & disown (instead of just &) should do.
Explanation:
system() spawns a shell that just executes one command and then exits. The & tells the shell to fork the command into background (means, it doesn't wait for its completion), but it's still part of the session and process group of the shell. When the group leader (the shell) exits, all children are killed. The disown causes the shell to start new process group, the child process is now owned by init (the first process in the system).
"Real" answer:
This is about programming. You are forking processes like crazy to accomplish something a C program could easily do using builtin library calls (except for the ssh but there are better ways, too). Go read on BSD sockets.
Related
According to my purpose, I just want to let my process be running in the background. Then I could write normal program and run it with the following command:
nohup myprogram 1>2 2>/dev/null &
Then this program will be running in the background, just like as a daemon.
With this way, I do not need to call fork() for running in background.
So my question is what is the difference to run program in background with the above command between using fork() function?
TL;DR the fork() call is not needed, it just helps providing a nice UI for the users of the program.
A daemon uses fork() to create a duplicate of it. The child process then keeps running (in the background). The parent process may produce some output (status) then it exits.
Of course you can write only the child part of the program and launch it using the command line you posted:
$ nohup myprogram 1>2 2>/dev/null &
But if you write the daemon and I have to use it, I certainly prefer to use a simpler command line, without all that scaffolding needed to put the program in background and ensure its output doesn't make it stop and so on:
$ myprogram # there is no need for anything else
My running process handles stdin by using getchar(). It works fine when I run it in foreground. However if I run it in background and do echo "a">> /proc/pid/fd/0 it won't work. On my system, /proc/pid/fd/0 is as same as /proc/pts/0, so how do I send to the process's stdin so that getchar() can see it? I'm working in C++ over ssh.
When you run multiple programs in background, they still have /dev/pts/XX as their control terminal (and stdin), but they are no longer eligible to read from it -- only shell or foreground task can do that. If they do, they'll get SIGTTIN signal that stops background process:
myaut#zenbook:~$ cat &
[1] 15250
myaut#zenbook:~$
[1]+ Stopped cat
Reasoning for such behavior is simple: multiple programs reading from one source leads to race condition. I.e. when you input to shell who am i, shell will read who, background task #1 will read am and task #2 will read i.
The solution is simple -- do not use pseudo-terminals to transfer data between processes:
Use pipes -- unnamed or named (with mkfifo). They are as simple as reading from stdin. Modern shells also provide coprocesses that allow to avoid named pipes.
Use UNIX sockets in complex cases
If you still need a pseudo-terminal, create a new one for your program with screen or other terminal emulator.
So here is the situation, we have a C++ datafeed client program which we run ~30 instances of with different parameters, and there are 3 scripts written to run/stop them: start.sh stop.sh and restart.sh (which runs stop.sh and then start.sh).
When there is a high volume of data the client "falls behind" real time. We test this by comparing the system time to the most recent data entry times listed. If any of the clients falls behind more than 10 minutes or so, I want to call the restart script to start all the binaries fresh so our data is as close to real time as possible.
Normally I call a script using System(script.sh), however the restart script looks up and kills the process using kill, BUT calling System() also makes the current program execution ignore SIGQUIT and SIGINT until system() returns.
On top of this if there are two concurrent executions with the same arguments they will conflict and the program will hang (this stems from establishing database connections), so I can not start the new instance until the old one is killed and I can not kill the current one if it ignores SIGQUIT.
Is there any way around this? The current state of the binary and missing some data does not matter at all if it has reached the threshold, I also can not just have the program restart itself, since if one of the instances falls behind, we want to restart all 30 of the instances (so gaps in the data are at uniform times). Is there a clean way to call a script from within C++ which hands over control and allows the script to restart the program from scratch?
FYI we are running on CentOS 6.3
Use exec() instead of system(). It will replace your process with the new one. Note there is a significant different in how exec() is called and how it behaves: system() passes its string argument to the system shell to run. exec() actually executes an executable file, and you need to supply the arguments to the process one at a time, instead of letting the shell parse them apart for you.
Here's my two cents.
Temporary solution: Use SIGKILL.
Long-term solution: Optimize your code or the general logic of your service tree, using other system calls like exec or by rewritting it to use threads.
If you want better answers maybe you should post some code and or degeneralize the issue.
For example,if i use system() command from a c program to invoke a shell command whether it will complete the shell command and then it'll proceed with program or it'll do both concurrently
what are all the various methods available to find this information ?
You can use fork() or exec() for non-blocking, but a system() call is blocking. This means it will wait for your shell command to finish prior to resuming executing of your C program.
Note if you want it to return right away, you can issue your system command with an & behind it and your C program will run concurrently.
Sequential Example:
system("long_script.sh");
Concurrent Example:
system("long_script.sh &");
In a Linux/C++ library I'm launching a process via the system() call,
system("nohup processName > /dev/null&");
This seems to work fine with a simple test application that exits on it's own, but if I use this from inside of a Nodejs/V8 extension which gets a kill signal, the child process gets killed. I did find that running,
system("sudo nohup processName > /dev/null&");
With the sudoers file set up to not require a password manages to make this run even when the parent process (node) exits. Is there someway to entirely detach the child process so signals sent to the parent and the parent exiting have no effect on the child anymore? Preferably within the system() call and not something that requires getting the process ID and doing something with it.
The procedure to detach from the parent process is simple: Run the command under setsid (so it starts in a new session), redirecting standard input, output and error to /dev/null (or somewhere else, as appropriate), in background of a subshell. Because system() starts a new shell, it is equivalent to such a subshell, so
system("setsid COMMAND </dev/null >/dev/null 2>/dev/null &");
does exactly what is needed. In a shell script, the equivalent is
( setsid COMMAND </dev/null >/dev/null 2>/dev/null & )
(Shell scripts need a subshell, because otherwise the COMMAND would be under job control for the current shell. That is not important when using system(), because it starts a new shell just for the command anyway; the shell will exit when the command exits.)
The redirections are necessary to make sure the COMMAND has no open descriptors to the current terminal. (When the terminal closes, a TERM signal is sent to all such processes.) This means standard input, standard output, and standard error all must be redirected. The above redirections work in both Bash and POSIX shells, but might not work in ancient versions of /bin/sh. In particular, it should work in all Linux distros.
setsid starts a new session; the COMMAND becoming the process group leader for its own process group. Signals can be directed to either a single process, or to all processes in a process group. Termination signals are usually sent to entire process groups (since an application may technically consist of multiple related processes). Starting a new session makes sure COMMAND does not get killed if the process group the parent proces belongs to is killed by a process-group wide signal.
My guess is that the whole process group is being killed. You could try setpgid in the child to start a new process group. The first step should be to get rid of system and use fork and execve or posix_spawn.