ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Welcome to LinuxQuestions.org, a friendly and active Linux Community.

You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!

Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.

If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.

Having a problem logging in? Please visit this page to clear all LQ-related cookies.

Introduction to Linux - A Hands on Guide

This guide was created as an overview of the Linux Operating System, geared toward new users as an exploration tour and getting started guide, with exercises at the end of each chapter.
For more advanced trainees it can be a desktop reference, and a collection of the base knowledge needed to proceed with system and network administration. This book contains many real life examples derived from the author's experience as a Linux system and network administrator, trainer and consultant. They hope these examples will help you to get a better understanding of the Linux system and that you feel encouraged to try out things on your own.

The daemon does its thing correctly, and the script does its thing correctly, except that the exit stauts returned by system() is not what I expect it to be: It remains stubbornly -1, indicating a failure in its fork() (the error message is "No child processes"). This is weird, because whichever script I call it runs fine and produces the expected results, so fork() must have created a child process for them somehow.

The daemon successfully forked off a child, exited the parent and got a new pid via setsid(). It also created its own lock file. It closed all file handles and reopened stdin, stdout, and stderr, redirecting them to /dev/null. But neither of the scripts use any of those standard IO channels - they just create a new log file in a writable directory, and I verified that this log file gets created and has correct content.

If I skip the daemonizing, the program works as expected.

I was under the impression that system() can be used in a daemon. If not, I'd like to be educated and also learn how else I would call a script and get its return code in a daemon. Any and all help will be highly appreciated.

Even though you're right, of course - I shoudl have given full path also in this little test case, but the script got executed, so it must have been found, and the consistency of the (bad) result is explainable.

The fork() creates a duplicate of the current process. They are independent, except they share open files and some other similar resources. The newly created process will see child_pid == 0, the other will see the PID of the newly created process instead. All other variables will have the same values (but changes will NOT be reflected in the other process; the values were just copied).

The execv() function takes two parameters: the first is the path to the script or program to be executed, and the second is an array of pointers to strings. The first element in the array corresponds to argv[0] for the executed program, i.e. should be the program name. The program above just executes whatever is specified as an argument. It does not search for the program in PATH; if you want it to, just use execvp(argv[1], argv + 1); instead. You could also use e.g. execl("/path/to/script", "scriptname", NULL); with optional parameters to the script listed as separate strings before the NULL.

There is an additional quirk when used in a daemon: you should provide sensible standard input, output, and error streams. The simplest option is to open them to /dev/null. Assuming your daemonize() function is typical, then it should do that already. If you do not trust the function does that, then you need a helper function,

The main difference between this approach and the system() library function is that this executes the other program directly, whereas system() always uses a shell. Basically, system() does something like the above, with execv("/bin/sh", "sh", "-c", "the-command-string", NULL); .

Most /bin/sh do not like to be executed without standard streams, and I suspect your daemonize() just closes the descriptors instead of opening them to e.g. /dev/null.

Waw - I am impressed. This is the most active (and helpful!!) forum I ever used.

First, to answer Reuti, I test for -1 because -1 is a special case in which the return code does not reflect the return code of the script at all (which may also be different from 0), but it reflects the failed fork, and there is no way to get to the return code of the script. If the return code is different from -1, it should reflect my script's return code (0 or different from 0 in case of an error in the script) and I can extract the return code that my script exited with using the WEXITSTATUS macro.

Secondly, to answer em31amit, yes, I am using exit in the bash script and sys.exit() in the Python script.

Thirdly, Nominal Animal, this is extremely helpful - thanks! Wrapping a shell around the script, as system() does, is indeed unnecessary, and I should be following the method you propose - just to avoid things that are not really necessary. And no, I do close all the file descriptors, but I re-open stdin, stdout, and stderr and point them all to /dev/null.

Finally, thanks a bunch bigearsbilly! My system does indeed have a daemon function, and using this avoids all of my problems. It is the first daemon I write, and so I was looking for tutorials on the web, which were didactically great, but not very effective, as they did not mention the built-in library function.

So for today, I have a "quick fix" by just using daemon(), but for the next couple of days, I will try to execute the scripts directly without the intermediate shell.