Fork, Setsid, and updating packages

Hi

I need to install a linux package (yocto/bitbake) .ipk, from inside my program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ( fork() == 0 ) {
    setsid();

    if ( fork() == 0 ) {
        execlp("/etc/ifmii/scripts/update.sh", (char *) nullptr);
    } else {
        int status;
        wait(&status);
        _exit(0);
    }
} else {
    int status;
    wait(&status);
    _exit(0);
}


While the script does run, it fails to utilize the package manager to actually install the package. Instead it just silently fails.

The script itself works, when run by hand. But when run from the actual systemd service it should replace, it just wont run through to the end.

Echo logs will be in the log file, until the actual install command. There it stops.

opkg install --force-options $(find packages) 2>&1 /update.log

It fails to log stderr and stdout from opkg.

Since i do not have anything to go with. No errors, nothing, i'm hoping someone can help with this.

I can run other opkg commands such as opkg list | opkg status pkg

I did try exec*(), system(), popen()/pclose() and the above is just the most current idea. But since the script generally starts, the problem has to be something else...

Last edited on
I don't know what's in the script, but I didn't think that was the way to run a script.

You need to run a shell, something like:
 
char* args[] = { "/bin/sh", "-c", "/etc/ifmii/scripts/update.sh", nullptr };

Also, I'm not sure why you're running it as a grandchild.
Last edited on
I'm running it as a grand child because it overwrites the binary of the program, after "systemctl disable" it.

So the problem is not that the script does not run, the problem is, that i does not run through.

I believe the script closes my program which then closes all the children and thus causing the script to not finish. This would happen when "opkg install" is run.

So what i need is a way to runn a command or script in a different scope. I need to fully detach it from its parent so that it does not die with the parent.


Your example does not compile btw.

UPDATE:

setsid(), setpgit(0,0) and daemon() do not help either.
Last edited on
I corrected my code, it wasn't what I meant. But I still think its the way you're running the script that's the problem.

I don't know what's in your script, so I'm not really clear about what you're saying.

You run something as a grandchild, then kill the child, to get the process owned by PID 1. But that doesn't apply in your case because 1) it isn't necessary, 2) you're not killing the child.
The exec* family has a few commands. I can start the script with all of them.

program (parent) -> child -> grandchild -> update.sh -> opkg install -> close parent -> closes all children

I need a way to detach my child from its parent so it survives its parents death which will always come.

Do you want to wait for the script to complete or run it asynchronously? I'm not sure why running a shell script has become so complicated.

No. Running the script is not the issue. Detaching the script so it lives on when the parent dies. AND THE PARENT ALWAYS DIES.

At some point i have to run "opkg install --some-flags <package>" which will result in a "systemd stop <process>" and since the "opkg"-call is a child of <process>, opkg will be killed too.

I tried using SSH to run this command in, or a screen session. But whatever i do, everything is start within my process will be killed as soon as "opkg" start.

UPDATE:

I think ive got a solution.

 
system("systemd-run opkg --switch install <package>");


This seems to work with no forking required.
Last edited on
No. Running the script is not the issue. Detaching the script so it lives on when the parent dies.

Ok, got it. You run the script as a grandchild, but you have to let the child die. When it dies, the grandchild becomes detached and a child of PID 1.
Registered users can post here. Sign in or register to post.