Thread: How correctly continue paused process?

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    53

    How correctly continue paused process?

    I have child process that paused. How better to continue it? At first glance better to send SIGCONT because by documentation pause returns after EVERY signal but...
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <string.h>
    
    int iceu_signals_init_signal_handler(const sigset_t ........et, __sighandler_t/*__sighandler_t*/ sgnhnd)
    {
      static struct sigaction sa_act;
      int i;
      //
      memset(&sa_act, 0, sizeof(sa_act));
      sa_act.sa_handler=sgnhnd;
      // blocking all signals while handler occurs:
      if (sigfillset(&(sa_act.sa_mask)))
      { 
        fprintf(stderr, "Cannot fill set of all signals\n");
        return 1;
      }
      for (i=1; i<=_SIGSET_NWORDS; i++)
      {
        switch (sigismember(sset, i))
        {
          case 1:
          if(sigaction(i, &sa_act, NULL))
          {        
            fprintf(stderr, "Cannot set signal %i(%s)\n",  i, sys_siglist[i]);
            return 10*i;  
          }
          break;
          case 0:
            continue;
          case -1: 
          {
            fprintf(stderr, "Cannot check signal membership: %i(%s)\n", i, sys_siglist[i]);
            return 5;
          }
        }  
      }
      return 0;
    }
    
    int iceu_signals_set_signals(sigset_t ........et, const int *set, int cnt)
    {
      int i;
      //
      if (sigemptyset(sset))
      {  
        fprintf(stderr, "Cannot do empty set of signals\n");
        return 1;
      }
      for (i=0;i<cnt;i++)
      {
        if (sigaddset(sset, set[i]))
        {
          fprintf(stderr, "Cannot add to set signal %i(%s)\n",  set[i], sys_siglist[set[i]]);
          return set[i]*100+1;
        }  
      }
      return 0;
    }
    
    static void ProcessSigHandler(int sg)
    {
      if (sg==SIGSTOP)
        fprintf(stderr, "Process stopped\n");
    }
    
    int main()
    {
      //1) register signals
      static sigset_t sset;
      int s=SIGSTOP;
      //
      if (iceu_signals_set_signals(&sset, &s, 1))
        return 1;
      iceu_signals_init_signal_handler(&sset, &ProcessSigHandler);
      fprintf(stderr, "Process started\n");
      pause();
      //kill(getpid(), SIGSTOP);
      kill(getpid(), SIGCONT);
      fprintf(stderr, "Process is about to terminate\n");
      return 0;
    }
    Simple test. Runned, after pausing i begin to send signals from other terminal. After this works everything but... CONT! Even SIGUSR1 works! What's going on? Why actually pause hasn't same behaivor as kill(getpid(), SIGSTOP)?

    ---------
    istead of ........ should be "*\ss" in code. Admins, do smth with editor, please
    Last edited by icegood; 12-04-2010 at 02:34 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Basic test.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    
    void h_sigstop ( int sig ) {
      printf("Never happens (%d)\n",sig);
    }
    void h_sigcont ( int sig ) {
      printf("Huh? what? (%d)\n",sig);
    }
    
    int main( void )
    {
      int i;
      printf("Running as PID=%d\n",getpid());
      signal(SIGCONT,h_sigcont);
      signal(SIGSTOP,h_sigstop);
      for ( i = 0 ; i < 10 ; i++ ) {
        printf("Loop=%d\n",i);
        if ( i == 5 ) kill(getpid(),SIGSTOP);
        sleep(2);
      }
      return 0;
    }
    Code:
    $ ./a.out &
    [2] 5380
    $ Running as PID=5380
    Loop=0
    Loop=1
    Loop=2
    Loop=3
    Loop=4
    Loop=5
    
    
    [2]+  Stopped                 ./a.out
    $ a=$!
    $ kill -s CONT $a
    Huh? what? (18)
    $ Loop=6
    Loop=7
    Loop=8
    Loop=9
    
    [2]+  Done                    ./a.out
    It forces itself to take a nap, and then I wake it up.
    Is this what you're trying to do?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    Almost that. I mean i want to do same via pair (pause(), kill(child_pid,SIGCONT)) instead of
    ( kill(my_pid,SIGSTOP), kill(child_pid,SIGCONT)).
    First procedure always called in child, second - in parent.
    Because i don't know how program will behave after sending itself SIGSTOP. Will it do smth before it really stops? You do for that sleep(2) just to clear signals queue. If it would be enough i will happy.
    Otherwise i should work via pair (pause(), kill(child_pid,SIGUSR1))

  4. #4
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    And yes, SIGSTOP hasn't handler. Maybe it means that it doesn't even go via signals queue and do that more directly. Then, of course, we don't need sleep(2). Everything wil be fine.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Sending SIGSTOP to yourself is "do not pass go, do not collect $200" territory.

    What about
    kill(child,SIGCONT); kill(self,SIGSTOP);

    and
    kill(parent,SIGCONT); kill(self,SIGSTOP);

    if you want them to alternate in some way?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    Quote Originally Posted by Salem View Post
    Sending SIGSTOP to yourself is "do not pass go, do not collect $200" territory.
    Nothing understood but sounds good
    Quote Originally Posted by Salem View Post
    What about
    kill(child,SIGCONT); kill(self,SIGSTOP);

    and
    kill(parent,SIGCONT); kill(self,SIGSTOP);

    if you want them to alternate in some way?
    Much more nicer then i've implemented.
    I continued parent process via
    Code:
    do
      {
        waitpid(child_pid_or_zero_for_parent, &status, WUNTRACED);
      } while (!WIFSTOPPED(status));
    it means that child should stop itself via SIGSTOP itself. But your solution much more clearer because it doesn't understood at all how child will change it state via sytem() calling in itself. So i need this loop

  7. #7
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    Of course, nothing works...
    Not so simple as it use to be... The reason is, for example, when i run kill(parent,SIGCONT); from child process that child should firstly return from kill otherwise uncontrollable execution of parent leads to "Interruptable system call" in some other system call. I.e. signal-safe kill() doesn't mean interprocess-glibc-safety. So, question remains same

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Perhaps you need a proper semaphore / mutex between them?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    Need! But how?

  10. #10
    Registered User
    Join Date
    Dec 2010
    Posts
    53
    WTF? Defenetly smth else happens! I inserted true thread-safe code in child process
    Code:
    while(1)
        {
          for(i=0;i<arrsize(buf_i);i++)
            buf_i[i]=i;
        }
    And child hangs inside this loop (i see that under debugger that i've attached to child)
    After that i try to continue parent and nothing good happens. Interrupted system call inside strtoll() somewhere in other place of world.
    Full code is:
    Code:
    #include "ice_system.h"
    #include <stdio.h>
    #include <unistd.h>
    
    #ifdef ice_system_call_light_weight_shell_task_imlemented
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    static FILE *exec_file=NULL;
    static const char *FileName="./ice_system_shell_task.sh";
    static pid_t child_pid_or_zero_for_parent, parent_id;
    static int EndChildProcess, ProcessContinued;
    static char buf[256];
    
    static int SendSignalToProcess(pid_t p_id, int sig_id)
    {
      if (kill(p_id, sig_id)==-1)
      {
        perror("SendSignalToProcess");
        fprintf(stderr, "There was troubles trying to send signal %d to process %d\n", sig_id, p_id);
        return 1;
      }
      return 0;
    }
    
    static inline void DoProceedChildProcess()
    {
    #ifdef debug
      fprintf(stderr, "Task from file %s is about to proceed\n", FileName);
    #endif
      if (system(FileName)==-1)
        perror("DoProceedChildProcess");
    #ifdef debug
      fprintf(stderr, "Task from file %s done\n", FileName);
    #endif
    }
    
    static inline void ChildProcessSigHandler(int sg)
    {
      if (sg==SIGUSR1)
        DoProceedChildProcess();
      else //SIGTERM
        EndChildProcess=1;
    }
    
    static inline void ParentProcessSigHandler(int sg)
    {
      ProcessContinued=1;
    }
    
    static inline int InitChildProcess()
    {
      //1) register signals
      static sigset_t sset;
      int v_signals[]={SIGTERM, SIGUSR1};
      //
      if (iceu_signals_set_signals(&sset, v_signals, arrsize(v_signals)))
        return 1;
      iceu_signals_init_signal_handler(&sset, &ChildProcessSigHandler);
      return 0;
    }
    
    static inline void RunChildProcess()
    {
      int buf_i[1024], i;
      //
      while(!EndChildProcess)
      {
        while(1)
        {
          for(i=0;i<arrsize(buf_i);i++)
            buf_i[i]=i;
        }
        pause();
        SendSignalToProcess(parent_id, SIGUSR1); // child just waits until will not ended
      }
      snprintf(buf, sizeof(buf), "rm -f %s", FileName);
      if (system(buf)==-1)
        perror("ice_system_call_light_weight_shell_task_free. system:");
      exit(0);
    }
    
    static inline int InitParentHandler()
    {
      static sigset_t sset;
      int v_signals[]={SIGUSR1};
      //
      if (iceu_signals_set_signals(&sset, v_signals, arrsize(v_signals)))
        return 1;
      iceu_signals_init_signal_handler(&sset, &ParentProcessSigHandler);
      return 0;
    }
    
    int ice_system_call_light_weight_shell_task_init()
    {
      // 1)
      if ((exec_file=iceu_system_safely_open_file(FileName, "w"))==NULL)
        return 1;
      fclose(exec_file);
      sprintf(buf, "chmod u+x %s", FileName);
      if (system(buf)==-1)
        return 1;
      if (InitParentHandler())
        return 1;
      ProcessContinued=0; // actually for parent
      switch (child_pid_or_zero_for_parent=fork())
      {
        case -1: // with errors will be in main window
        {
          perror("fork");
          return 1;
        }
        case 0: // child process
        {
          if (InitChildProcess())
            exit(0);
          parent_id=getppid();
          EndChildProcess=0;
          SendSignalToProcess(parent_id, SIGUSR1); // child just waits until will not ended
          RunChildProcess();
        }
        default:  // parent process
        {
          while(!ProcessContinued)
            sleep(2); // wait for initialization of child
        #ifdef debug
          fprintf(stderr, "Parent id is %d\n", getpid());
          fprintf(stderr, "Child id is %d\n", child_pid_or_zero_for_parent);
        #endif
        }
      }
      return 0;
    }
    
    void ice_system_call_light_weight_shell_task_free()
    {
      pid_t pid;
      int status;
      //
      if (child_pid_or_zero_for_parent!=-1)
      {
        SendSignalToProcess(child_pid_or_zero_for_parent, SIGTERM);
        // now wait until it really exited:
        while(((pid=waitpid(child_pid_or_zero_for_parent, &status, 0))!=child_pid_or_zero_for_parent)||
          (!WIFEXITED(status)))
        {
          if(pid<=0)
          {
            fprintf(stderr, "Error occured trying to end child\n");
            break;
          }
        }
      }
    }
    #endif //ice_system_call_light_weight_shell_task_imlemented
    
    // dislike to system() call this one is lightweighted provided there is no fork call so there is no memory consumption
    int ice_system_call_light_weight_shell_task(const char *task)
    {
    #ifndef ice_system_call_light_weight_shell_task_imlemented
      if (system(task)==-1)
      {
        perror("ice_system_call_light_weight_shell_task");
        return 1;
      }
    #else
      if ((exec_file=iceu_system_safely_open_file(FileName, "w"))==NULL)
        return 1;
      fprintf(exec_file, "#!/bin/bash\n%s\nexit 0", task);
      fclose(exec_file);
      ProcessContinued=0;
    #ifdef debug
      fprintf(stderr, "Task \"%s\" is about to proceed\n", task);
    #endif
      if (SendSignalToProcess(child_pid_or_zero_for_parent, SIGUSR1))
        return 1;
      while(!ProcessContinued)
        sleep(1);
      /*
      if (SendSignalToProcess(parent_id, SIGSTOP))
        return 1;
      */
    #endif
      return 0;
    }
    I don't get it! WTF? Maybe after fork child and parent had smth common that shouldn't be common anymore?
    Last edited by icegood; 12-06-2010 at 08:25 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to get process info ( to extract process thread id )
    By umen242 in forum C++ Programming
    Replies: 4
    Last Post: 02-12-2009, 01:08 PM
  2. One process with two console windows
    By siavoshkc in forum Windows Programming
    Replies: 8
    Last Post: 01-30-2009, 04:13 PM
  3. need help making a dot bounce up and down y axis in this prog
    By redwing26 in forum Game Programming
    Replies: 10
    Last Post: 08-05-2006, 12:48 PM
  4. Sending a message to parent from child process
    By maxorator in forum C++ Programming
    Replies: 2
    Last Post: 10-09-2005, 04:23 PM
  5. process ring
    By gregulator in forum C++ Programming
    Replies: 0
    Last Post: 02-28-2005, 08:21 PM