don't allow program to kill any not realted processes - linux

I'm currently learning how to use system calls such as fork, exec*, and kill. I had a task that required to send SIGKILL to all parent's sibilngs created with fork if one of fork calls failed. So I did smth like this:
for (int i = 0; i < numOfchilds; i++) {
childs[i] = fork();
if (childs[i] == -1)
killAll(childs, i);
...
void killAll(pid_t childs, size_t numOfChilds) {
for (int i = 0; i < numOfChilds; i++)
kill(childs[i], SIGKILL);
}
But I messed up and accidentally send kill(-1, SIGKILL) and killed all processe that I could. Fortunately I didn't lose any unsave data, but kill -9 -1 is not the best practice to logout.
So. Is there any way I can restrict my program killing any processes that don't belong to it, so it could only kill one it created with fork?

Related

How to propagate signal in C from parent to child which are in own process group?

Suppose I have 10 child processes which are moved to their own process group by setpgid(0,0) just before the exec. (Each child also has children which are also in their own process group.)
My foreground process gets ctrl-c SIGINT signal and I want to propagate it to the all child processes (all children are in different group). How to do that?
hope that quick draft better explain my problem.
void handler(int signal) {
// resend SIGINT to all childs but childs are in different pgid
}
int main(int argc, char* argv[]){
struct sigaction sa;
sa.sa_handler = &handler;
sigaction(SIGINT, &sa, NULL);
pid_t pid[SIZE];
int i = 0;
// if argv is ge 2;
for (;i < SIZE; i++) // SIZE is number of the elements in argv
{
pid[i] = fork();
if(pid[i] == 0)
{
setpgid(0,0);
// execv self here but with one less element in argv;
}
}
while(1){}; // infinity loop (waits for ctrl-c from foreground process)
// prints to the terminal pid and pgid
// waits here for all childs to finish and then close self
}
What about forwarding the signal in the signal handler of main process, manually. Maybe you can provide some code snippet to clarify the situation you're in.
void signalHandler(int signum)
{
kill(child_pid,signum);
//other stuff
}

How to synchronize input and output in pipes linux?

I am creating a shell command from the custom shell to do the ssh from one terminal to another terminal.
In order to do the ssh, I am using the inbuilt ssh command of the linux. Here is my code that does the ssh login.
However, I am seeing that the I/O buffers are not in sync.
This is what I am seeing on the terminal. After SSH to the other terminal. I did the following in the terminal.
PRT# ssh 192.168.10.42
PRT# Could not create directory '/root/.ssh'.
root#192.168.10.42's password:
# screen -r
-sh: cen-: not found
# hello
-sh: el: not found
#
I don't what's the reason here. Here is the code.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
}
return 0;
}
Based on Patrick Ideas.
POST 2# - It seems that it works when we close the stdin in the parent process. However, it becomes very slugguish, I feel like I am typing the keyboard too slow. The system becomes too sluggish. Also, I have a web-server from this terminal. I see that I can no longer access the web.
So, the solution is somewhere around stdin but I am not sure.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
close(stdin);
}
return 0;
}
Basically, I have added - close(stdin);
You have 2 different processes trying to read from STDIN. This causes process 1 to get char 1, process 2 to get char 2, process 1 to get char 3, process 2 to get char 4, etc, alternating back and forth.
Your 2 processes are:
execlp("ssh", "ssh", "-tt", destIp, NULL);.
while( (read(fd[0], readbuff, sizeof(readbuff))))
Basically you need to ditch the read(fd[0],...).
My initial thought is that perhaps it is buffering the output: stdout is buffered, so unless you print a newline, nothing will be printed until a certain number of characters build up. This is because I/O operations are expensive. You can find more detail on this here. The result is that there is a delay because your program is waiting to print.
My suggestion: in your main function, before calling your sshLogin function, try disabling buffering with this line of code:
setbuf(stdout, NULL);
You can also call fflush(stdout); periodically to do the same thing, but the above method is more efficient. Try it and see if that solves your problem.

How much time it takes to create process from process

I am trying to create a new process from an existing process.
like that parentMain process creates childMain process.
my goal is:
1) Both process will continue running (means no one should wait for another to finish)
2) The creator - parentMain process, should send a message to the created process - childMain process.
I do not know when the new childMain process is actually ready. I can not use the wait function as I understood it waits until
the child process should end, but my aim is it will continue to run.
After little googling I am using the fork & exec family functions as follows:
void parentMain::CreateAndSend()
{
createNewProcess();
sendMessage();
}
void parentMain::createNewProcess()
{
char* param1[10] = "param1";
// Create new process.
cpid = fork();
if (cpid >= 0) // fork() succeeded.
{
if (cpid == 0) // 0 for child process.
{
execl("/home/kon/childMain", "/home/kon/childMain", param1, (char*)0);
}
else /* parent process */
{
printf("Parent process, parent PID=%d child PID=%d, getpid(), cpid);
}
}
else // fork() failed.
{
printf("Failure");
}
}
void parentMain::sendMessage()
{
Y = 50; // milliseconds.
nanosleep(Y);
?? isChildReady ??
sendChildMessage();
}
Now, sometimes sendMessage() fails!
if I am using a sleep(X) it succeeded. (in seconds)
but I want to reduce the time as much as I can.
How much time it takes to a process to be created?
is there any function that says "child is ready"?
How can I do it?
Thanks

About Inter-process communication in C, Using pipe()

I'm trying to write sort function.
This function may fork many children to help itself to sort the given input.
When my function has only one child it is easy to use pipe(). I just create
int fd[2];
then everything is fine but I don't know what to do when there are many children. Should I create fd[Children*2] pipes or fd[2] is enough?
And how can i use these pipes to communicate with the child that I want (since there are many children)?
My main process will fork children, this is just one part of the code, I'm forking children and getting their pids into pid array
pid_t main = getpid();
int N = 30;
pid_t* children = (pid_t*) malloc(sizeof(pid_t) * N);
for(i = 0; i < N; i++){
pid_t child = fork();
if ( child == 0){
pid_t me = getpid();
printf("I'm a child and my pid is: %d\n", me);
sleep(1);
// exit(4);
return me * 2;
} else if ( child < 0){
// printf("Could not create child\n");
} else {
children[i] = child;
// printf("I have created a child and its pid %d\n", child);
}
}
If only the main process needs to create and communicate with children, and the children don't need to communicate with each other, create a separate pipe for each child in the main process before forking the child. The call to pipe() could be placed in your loop, before calling fork(). You could use a 2-dimensional array like fd[NUM_CHILDREN][2] to keep track of the file descriptors. If the data will be arriving asynchronously, poll() or select() can be used to find out when something is available to be read.

Real forking UDP server asserts and core dumps

This worked flawlessly in node 0.6.19 but now fails.
I wrote a forking UDP server in node. However, node doesn't have a real fork and cluster doesn't do UDP, so I wrote a module in C++ that simply calls fork (the module that contains this function is called "hasher")
static Handle<Value> spoon(const Arguments& args) // node sees this function as "fork"
{
HandleScope scope;
pid_t rval = fork();
if (rval < 0)
{
return ThrowException(Exception::Error(String::New("Unable to fork daemon, pid < 0.")));
}
Handle<Value> n = v8::Number::New(rval);
return n;
}
I bind the UDP port, and fork all the children.
udp_server.bind(argv.udp_listen_port, '0.0.0.0');
// now create multiple children (loop starting with 1 is on purpose)
for (var i = 1; i < argv.multiple; i++)
{
var pid = hasher.fork();
if (pid == 0)
break;
}
Theoretically, the child processes should not know that someone else is sharing that port and should behave normally. However, I almost immediately (1 or 2 incoming UDP packets) trigger an assert message:
node-0.10.29: ../deps/uv/src/unix/stream.c:499: uv__server_io: Assertion `events == 1'
failed.
Aborted (core dumped)
Anyone have a clue as to what is going on?

Resources