Ubuntu-Daemon does not create file - c

I'm trying to run a simple daemon on Ubuntu 18.04.2 LTS, which should write some data into a log file. The parent process terminates with exit code 0, but no file is created.
Furthermore, when I set a breakpoint after fork(), pid is 835 for example. When I query the process name of this program with ps -p 835 -o comm=, I get LinuxTest.out <defunct>, but when I let the program continue and query the process name again, no output is shown, even though the child process should be still running due to the infinite loop later in the code.
I am using Visual Studio 2019 with Remote Build. I have also tried to log in per SSH into the server and execute the built program there with sudo rights, but nothing happened too.
int main() {
pid_t pid, sid;
// Fork off the parent process
pid = fork();
// if we got a good PID, then we can exit the parent process
if(pid > 0) exit(EXIT_SUCCESS);
else exit(EXIT_FAILURE);
// create new SID for child process
sid = setsid();
if(sid < 0) exit(EXIT_FAILURE);
// change the current working directory
if(chdir("/") < 0) {
exit(EXIT_FAILURE);
}
// change the file mode mask
umask(0);
// close out the standard file descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// Open a log file in write mode.
FILE* fp = fopen("Log.txt", "w+");
while(1) {
sleep(1);
fprintf(fp, "Logging info...\n");
fflush(fp);
}
fclose(fp);
}
Why is the point to create the file not reached and why doesn't stay the child process alive?

You have:
if(pid > 0) exit(EXIT_SUCCESS);
else exit(EXIT_FAILURE);
When formatted in a more orthodox style, that is the same as:
if (pid > 0)
exit(EXIT_SUCCESS);
else
exit(EXIT_FAILURE);
If the fork() succeeds, the parent exits successfully and the child exits with a failure status; if the fork() fails, the parent exits with a failure status.
Change that to:
if (pid > 0)
exit(EXIT_SUCCESS);
else if (pid < 0)
exit(EXIT_FAILURE);
/* Child is running here: pid == 0 */

Related

Execution of UNIX command is being outputted after I exit the program

For some unknown reason, when I'm executing piped commands in my shell program, they're only outputting once I exit the program, anyone see why?
Code:
int execCmdsPiped(char **cmds, char **pipedCmds){
// 0 is read end, 1 is write end
int pipefd[2];
pid_t pid1, pid2;
if (pipe(pipefd) == -1) {
fprintf(stderr,"Pipe failed");
return 1;
}
pid1 = fork();
if (pid1 < 0) {
fprintf(stderr, "Fork Failure");
}
if (pid1 == 0) {
// Child 1 executing..
// It only needs to write at the write end
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
if (execvp(pipedCmds[0], pipedCmds) < 0) {
printf("\nCouldn't execute command 1: %s\n", *pipedCmds);
exit(0);
}
} else {
// Parent executing
pid2 = fork();
if (pid2 < 0) {
fprintf(stderr, "Fork Failure");
exit(0);
}
// Child 2 executing..
// It only needs to read at the read end
if (pid2 == 0) {
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
if (execvp(cmds[0], cmds) < 0) {
//printf("\nCouldn't execute command 2...");
printf("\nCouldn't execute command 2: %s\n", *cmds);
exit(0);
}
} else {
// parent executing, waiting for two children
wait(NULL);
}
}
}
Output:
In this example of the output, I have used "ls | sort -r" as the example, another important note is that my program is designed to only handle one pipe, I'm not supporting multi-piped commands. But with all that in mind, where am I going wrong, and what should I do to fix it so that it's outputting within the shell, not outside it. Many thanks in advance for any and all advice and help given.
The reason would be your parent process file descriptors are not closed yet. When you wait for the second command to terminate, it hangs because the writing end is not closed so it wait until either the writing end is closed, or new data is available to read.
Try closing both pipefd[0] and pipefd[1] before waiting for process to terminate.
Also note that wait(NULL); will immediately return when one process has terminated, you would need a second one as to not generate zombies if your process still runs after that.

Interrupt a process calling the function popen

I need to implement a child process that will execute a file and send the execution result, the 2 process will communicate with a shared memory segment.
My problem is that i want to kill the child process calling popen after 10 seconds but the function popen ignores signals.
Here is my code (shared memory segment not included) :
void kill_child(int sig)
{
kill(child_pid,SIGKILL);
printf("processus killed \n");
}
/*code....*/
signal(SIGALRM,(void (*)(int))kill_child);
if(fork()==0){
res.buffer=true;
FILE * fd;
char cmd[BUFFER_SIZE],output[BUFFER_SIZE];
strcpy(cmd,"./");
strcat(cmd,res.filepath);
system(cmd);
if((fd=popen(cmd,"r"))== NULL)
exit(1);
else
res.status=200;
strcpy(output,"");
while(fgets(buf,sizeof(buf)-1,fd))
strcat(output,buf);
if(pclose(fd))
exit(1);
strcat(res.customHTML,output);
res.buffer=true;
int err = sendResponse(res,args->client_fd);
if (err < 0) on_error("failed!\r\n");
exit(0);
}
else{
int status;
alarm(10);
waitpid(-1,&status,0);
printf("status %d _n);
}
How can make the child process interruptible?
thanks
First off, you need to actually store the child PID into child_pid. It's returned from fork for the parent process so changing your fork call to
child_pid = fork();
if(child_pid == 0)
{
...
otherwise your call to kill is being passed a random value. Luckily it seems to be defaulting to 0, which kill takes to mean kill all processes in the same process group so your child process is being killed.
Secondly, rather than calling popen() call the executable yourself with (for example) execvp() and have the parent read the output using a pipe you create yourself...
int fds[2];
pipe(fds);
child_pid = fork();
if(child_pid == 0)
{
char *cmd[]={"mycmd",NULL};
/* Replace stdout with the output of the pipe and close the original */
dup2(fds[1],1);
close(fds[0]);
close(fds[1]);
execvp(cmd[0],cmd);
}
else
{
close(fds[1]);
alarm(10);
while(...)
{
read(fds[0],....);
if(waitpid(child_pid,&status,WNOHANG))
{
....
}
}
}
This way you've only got the one child process which is running your executable and you've got visibility on when and how it exits.

Which process is getting exited and why is close(0) call followed after exit(0)

if (log_daemon) {
pid_t pid;
log_init();
pid = fork();
if (pid < 0) {
log_error("error starting daemon: %m");
exit(-1);
} else if (pid)
exit(0);
close(0);
open("/dev/null", O_RDWR);
dup2(0, 1);
dup2(0, 2);
setsid();
if (chdir("/") < 0) {
log_error("failed to set working dir to /: %m");
exit(-1);
}
}
I have above c program, and couldnt figure out what does the exit(0); do in this case, which process does it exit? and what does the close(0); is followed for? Will the close(0); even execute?
Is this code just to test whether a child process can be created?
UPDATE:
ok, I got it from this question Start a process in the background in Linux with C.
Basically, close(0); does is closes current standard input for child process and opens /dev/null as input device. This way child process will behave as a deamon and will not read anything from terminal or standard input.
The fork returns the process id in the parent process, and 0 in the child process. The main calling process is exiting becausepid == 0 so if (pid) is true in the parent, and false in the child. The child then proceeds to close(0), etc.

two forks and the use of wait

Currently am doing two forks to pipeline two process, but I think am doing my wait(&status) wrong because after the command my shell just hangs and does not return to my prompt. I know my pipe is working because I can see the result if I remove the wait.
Any tips?
pipe(mypipe);
pid1=fork();
if(pid1==0)
{
pid2=fork();
if(pid2==0)
{
close(0);
dup(mypipe[0]);
close(mypipe[1]);
execv(foundnode2->path_dir,arv2);
exit(0);
}
close(1);
dup(mypipe[1]);
close(mypipe[0]);
pid2 = wait(&status2);
execv(foundnode1->path_dir,arv1);
exit(0);
}
pid1 = wait(&status2);
Rule of Thumb: if you use dup() or dup2() to map one end of a pipe to standard input or standard output, you should close() both ends of the pipe itself. You're not doing that; your waits are waiting for the programs to finish but the programs will not finish because there is still a proess with the pipe open that could write to the pipe. Also, the process which created the pipe needs to close both ends of the pipe since it is not, itself, using the pipe (the child processes are using it). See also C MiniShell — Adding Pipelines.
Also, you should not be waiting for the first child to finish before launching the second (so the pid2 = wait(&status2); line is a bad idea). Pipes have a fairly small capacity; if the total data to be transferred is too large, the writing child may block waiting for the reading child to read, but the reading child hasn't started yet because it is waiting for the writing child to exit (and it takes a long time for this deadlock to resolve itself). You're seeing the output appear without the wait() calls because the second part of the pipeline executes and processes the data from the first part of the pipeline, but it is still waiting for more data to come from the shell.
Taking those tips into account, you might end up with:
pipe(mypipe);
pid1 = fork();
if (pid1 == 0)
{
pid2 = fork();
if (pid2 == 0)
{
close(0);
dup(mypipe[0]);
close(mypipe[1]);
close(mypipe[0]);
execv(foundnode2->path_dir, arv2);
fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
exit(1);
}
close(1);
dup(mypipe[1]);
close(mypipe[0]);
close(mypipe[1]);
execv(foundnode1->path_dir, arv1);
fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
exit(1);
}
close(mypipe[0]);
close(mypipe[1]);
pid1 = wait(&status1);
Notice the error reporting to standard error when the commands fail to execv(). Also, the exit status of 0 should be reserved for success; 1 is a convenient error exit status, or you can use EXIT_FAILURE from <stdlib.h>.
There is a lot of error checking omitted still; the fork() operations could fail; the pipe() might fail. One consequence is that if the second fork() fails, you still launch the second child (identified by foundnode1->path_dir).
And I note that you could save yourself a little work by moving the pipe creation into the first child process (the parent then does not need to — indeed, cannot — close the pipe):
int pid1 = fork();
if (pid1 == 0)
{
int mypipe[2];
pipe(mypipe);
int pid2 = fork();
if (pid2 == 0)
{
close(0);
dup(mypipe[0]);
close(mypipe[1]);
close(mypipe[0]);
execv(foundnode2->path_dir, arv2);
fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
exit(1);
}
close(1);
dup(mypipe[1]);
close(mypipe[0]);
close(mypipe[1]);
execv(foundnode1->path_dir, arv1);
fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
exit(1);
}
pid1 = wait(&status1);
If it's just a pipe with two processes, I wouldn't wait at all. Just fork and do an exec in parent and child.
int fd[2];
pipe(fd);
int pid = fork();
if (pid == -1) {
/* error handling */
} else if (pid == 0) {
dup2(fd[0], 0);
close(fd[1]);
execv(foundnode2->path_dir,arv2);
/* error handling for failed exec */
exit(1);
} else {
dup2(fd[1], 1);
close(fd[0]);
execv(foundnode1->path_dir,arv1);
/* error handling for failed exec */
exit(1);
}

Redirecting forked process output to parent process in C

What I am implementing is a (simpler) version of bash. One of the tasks is to accept the command :
$ bg <command> <arguments>
This will then fork a new process and then run execvp() in the new process using <command> and <arguments> as parameters. The problem is that when I capture the output from the child process, I use pipe(), and after getting the output from the child process and outputting it when I want, I can't seem to switch back to STDIN for my parent (shell) process, which results in a segfault the next time I need to accept input.
Here is part of my "bg" function.
ChildPID = fork();
if (ChildPID < 0) {
/* There is an error */
printf("Error forking the process.\n");
exit(1);
}
if (ChildPID >= 0) {
if (ChildPID == 0) { /* Child Process */
close(m_pipefd[0]);
dup2(m_pipefd[1], STDOUT_FILENO);
close(m_pipefd[1]);
//sleep(5);
err = execvp(optionsPTR[0], optionsPTR);
switch (errno) {
case ENOENT:
printf("RSI: %s: command not found\n", optionsPTR[0]);
break;
case EACCES:
printf("RSI: %s: Permission denied\n", optionsPTR[0]);
break;
}
exit(1);
}
else { /* Parent Process */
WaitErr = waitpid(ChildPID, &status, WNOHANG | WUNTRACED);
return(0); /* to main */
}
}
return 0;
And the code for when I get the output from the pipe after the process finishes.
close(m_pipefd[1]);
dup2(m_pipefd[0], STDIN_FILENO);
while(fgets(buffer, sizeof(buffer), stdin)) {
buf = buffer;
printf("%s\n", buf);
}
close(m_pipefd[0]);
So the tl;dr version is that I need to reset back to stdin for the parent process after capturing the child processes output.
Thanks,
Braden
There is usually no need to mess with stdin and stdout in your parent. After you connect your pipes in the child to stdin and stdout, the other ends of the pipes should be able to send data or get data from the child.
Just read from m_pipefd[1] in your parent.

Resources