barp
barp

Reputation: 6929

execv call in C

There is a simple program below that takes a HUP and continues with execv. The problem is when the execv call is executed, after that the code continues from the places where the HUP comes.I want, after execv the code must exit from main and than start again from the beginning of main.

char* a;
char** args;

void hup_func(){
    printf("aaaa\n");
    if(execv(a,args))
        printf("bbb\n");
}

int main(int argc,char* argv[]){
    signal(SIGHUP,hup_func);
    args=argv;
    a=args[0];
    printf("%s\n",a);
    while(1){
        printf("test\n");
        sleep(10);
     }

   return 0;
}

The name of the program is deneme1. The output of the code is when I sent HUP;

./deneme1
test
test
aaa 
bbbb
test.

But I want it, when I sent HUP, it must start with the start of the main. like that

./deneme1
test
test
aaa
bbb
./deneme1
test
...

I want it to return at the beginning of the main after HUP, not the place where it was before

Upvotes: 1

Views: 2574

Answers (3)

Jason
Jason

Reputation: 32510

You're not sending the correct arguments to execv, and therefore the function is exiting with an error. So you're simply exiting the signal handler rather than overlaying the process with a new copy of the process.

The argument signature for execv is:

int execv(const char *path, char *const argv[]); 

The second argument should be an array of const pointers to char, with the last element being a NULL pointer. The char* a that you're passing for the second argument is not the correct type.

Finally, execv is not considered an asynchronous signal-safe function, where-as it's sister-function, execve is. You should use the latter. The same is also true for any of the printf family of functions ... if you need to write to the terminal, use write instead.

Update: I re-ran your updated code. The program is restarting properly, but the problem is that the signal mask is being inherited from the original process that was overlaid by the call to execv. Since you are running execv from inside a signal-handler, the SIGHUP will be blocked in the overlaid process, and you won't be able to send any other SIGHUP signals to the process. To undo this, you need to unblock the SIGHUP signal using sigprocmask() right after you assign your signal-handler using signal().

For instance, change your main to:

int main(int argc,char* argv[])
{
    sigset_t signal_mask;

    signal(SIGHUP,hup_func);

    //unblock the SIGHUP signal if it's blocked
    sigaddset(&signal_mask, SIGHUP);
    sigprocmask(SIG_UNBLOCK, &signal_mask, NULL);

    args=argv;
    a=args[0];
    printf("%s\n",a);
    while(1){
        printf("test\n");
        sleep(10);
     }

   return 0;
}

I've compiled and run this on Ubuntu 12.04, and it now runs perfectly.

Upvotes: 2

tuxuday
tuxuday

Reputation: 3037

As @Jason pointed, execv is failing. Test yourself with this code.

#include<signal.h>
char* a;
char **args;

void hup_func(){
    printf("receivied SIGHUP\n");
    execv(a,a);
    printf("execv failed\n");
}

int main(int argc,char* argv[]){
    int b =0;
    printf("setting signal handler for SIGHUP\n");
    signal(SIGHUP,hup_func);
    args=argv;
    a=argv[0];
    printf("Before entering while %s\n",a);
    while(1){
        printf("In while %d\n",++b);
        sleep(1);
     }

   return 0;
}

Then replace

   execv(a,a);

with

   execv(a,args);

Upvotes: 0

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136238

The problem is when the execv call is executed, after that the code continues from the places where the HUP comes

There is no error checking in your code, most likely execv() call fails.

Try amending it like:

char** gargv;

void hup_func() {
    execvp(*gargv, gargv);
    abort(); // must never get here
}

int main(int argc,char* argv[]) {
    // ...
    gargv = argv;
    // ...

Upvotes: 0

Related Questions