lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: lynx-dev Problem with ^Z suspending


From: Kari E. Hurtta
Subject: Re: lynx-dev Problem with ^Z suspending
Date: Wed, 27 Jan 1999 10:08:09 +0200 (EET)

Klaus Weide:
> [ On a different tangent: ] 
> > Well... Lynx already forks a lot due to NSL_FORK.  It might be better if
> > there were two always-running coprocesses, one to do lookups and one to
> > interact with the user.
> 
> Or like squid with its external dnsserver processes... (they communicate
> via sockets.)
> 
> > The interactive one could very well be the
> > child, in which case it's no big deal to also-by-the-way make it its own
> > pgrp.  
> 
> Would confuse parent interactive shell, which wouldn't know to kill it
> with SIGHUP on exit etc.

Well, that other process what is forked (to keep origianl process group;
or which way you arrange it), will get that SIGHUP [**] (because it is on
process group for which shell knows about). [*]


And it is anyway good to check errors when read from terminal
(it will fail when terminal is closed on exit).

/ Kari


Please ignore rest....
This is going to to detailed.
And I do not know was that best method...
And there is really many not so nice details.



[*] Actually that my program (from some years ago) when was suspending 
    itself put it first to original process group.


void handle_sigtstp(int sig) {   /* User have pressed Ctrl-Z */
  /* In SUNOS5 we need block SIGTTOU */
  if (DEBUG_SIGNAL) 
    print_error2(P_DEBUG,"Got   SIGTSTP (sig=%d)", sig);

  reset_terminal_state();   /* Give original terminal characters */
  flush_buffer(0);          /* and print it to terminal */
  set_caller_ttystate();   
  
  deliver_signal(sig); /* Now my callers turn */

  stop_me();

  set_pager_ttystate();
  need_redraw = 1;

  if (DEBUG_SIGNAL) 
    print_error2(P_DEBUG,"Done  SIGTSTP (sig=%d)", sig);
}

Where:

void set_caller_ttystate(void ) {
  if (!termios_set) return;
 again1:
  if (-1 == tcsetattr(terminal,TCSADRAIN,&tty_origstate)) {
    int code = errno;
    if (EINTR == code) goto again1;
    print_error2(code,
                 "(%P) set_caller_ttystate/Can't restore tty state for 
/dev/tty");
  } else tty_state_set = 0;

  if (have_group) {
  again2:
    if (-1 == tcsetpgrp(terminal,oldgroup)) {
      
      int code = errno;
      if (EINTR == code) goto again2;
      
      print_error2(code,
                   "(%P) set_caller_ttystate/Can't change terminal group to %d",
                   oldgroup);
    } else if(DEBUG_SIGNAL || DEBUG_TERM)
      print_error2(P_DEBUG,"Terminal group is now restored to %d",oldgroup);
  }
}

and:

static void stop_me(void) {

  if (have_group && mypid != oldgroup) {
    if (-1 == setpgid(mypid,oldgroup)) {
      int code = errno;
      print_error2(code,
                   "SUSPENDING CANCELED!\n(%P) stop_me/Can't join again my old 
group = %d",
                   oldgroup);
      
      /* IF we now stop, we stuck when kehpager is resumed !!! */
      return;
    } else if (DEBUG_SIGNAL || DEBUG_TERM)
      print_error2(P_DEBUG,"Joined to old terminal group %d",oldgroup);
  }

  if (DEBUG_SIGNAL)
    print_error2(P_DEBUG,"Sending SIGSTOP to myself");
  kill(mypid,SIGSTOP);
  if (DEBUG_SIGNAL)
    print_error2(P_DEBUG,"Woked up from SIGSTOP");

  if (have_group && mypid != oldgroup) {
    if (-1 == setpgid(mypid,mypid)) {
      int code = errno;
      print_error2(code,
                   "(%P) stop_me/Can't recreate again my new group = %d (my 
pid)",
                   mypid);
      have_group = 0;
    } else if (DEBUG_SIGNAL || DEBUG_TERM)
      print_error2(P_DEBUG,"Joined to new terminal group %d (my pid)",mypid);
  }
}

and:

static void deliver_signal(int sig)  {
  if (!have_group || mypid == oldgroup) return;
  
  if (-1 == kill(-oldgroup,sig)) {
    int code = errno;
    print_error2(code,"(%P) deliver_signal/Can't deliver signal %d to group %d",
                 sig,oldgroup);
  } else if (DEBUG_SIGNAL) 
    print_error2(P_DEBUG,"Signal %d delivered to group %d",sig,oldgroup);
}

And:

void set_pager_ttystate(void) {
  if (!termios_set) return;
  
  check_terminal_group();

  if (have_group) {
    sigset_t oldmask,blockmask;
    
    sigemptyset(&blockmask);
    sigaddset(&blockmask,SIGTTOU);
    if (-1 == sigprocmask(SIG_BLOCK,&blockmask,&oldmask)) {
      int code = errno;
      print_error2(code,"(%P) set_pager_ttystate/Can't block SIGTTOU");
    } else {
      
    again0:
      if (-1 == tcsetpgrp(terminal,mypid)) {
        
        int code = errno;
        if (EINTR == code) goto again0;
        
        print_error2(code,
                     "(%P) set_pager_ttystate/Can't change terminal group "
                     "to %d (my pid)",
                     mypid);
      } else if(DEBUG_SIGNAL || DEBUG_TERM)
        print_error2(P_DEBUG,"Terminal group is now changed to %d (my pid)",
                     mypid);
      
      if (-1 == sigprocmask(SIG_SETMASK,&oldmask,NULL)) {
        int code = errno;
        print_error2(code,"(%P) set_pager_ttystate/Can't unblock SIGTTOU");
      }
    }
  }

 again1:
  if (-1 == tcsetattr(terminal,TCSADRAIN,&tty_state)) { /* when output is wrote 
*/
    int code = errno;
    if (EINTR == code) goto again1;
    print_error2(code,"(%P) set_pager_ttystate/Can't change tty state of 
/dev/tty");
  } else tty_state_set = 1;
  get_winsize(1);
}

And this is nasty part. Do not change terminal process group if
you are not currently on foregroup group of terminal:    :-)

static void check_terminal_group(void) {
  int cgroup;
 again:
  while (oldgroup != (cgroup = tcgetpgrp(terminal))) {
    if (-1 == cgroup) {
      int code = errno;
      if (EINTR == code) goto again;

      terminal_have_lost = 1; /* default */
 
      print_error2(code,"(%P) check_terminal_group/Can't get current group");
      QUIT_pager(0);
    }
    if(DEBUG_SIGNAL)
      print_error2(P_DEBUG,"Terminal group = %d, my group = %d. Suspending...",
                  cgroup,oldgroup);
        
    kill(mypid,SIGSTOP); /* wait that I am in foreground */

    if(DEBUG_SIGNAL)
      print_error2(P_DEBUG,"Wake up");
  }
}

[**]

static void friend_have_died(int res) {
  if (allow_dead) return;
  print_error2(P_NOTIFY,"(%P) Reserver process (%d) died - exiting (%d)...",
               res,mypid);

  myfriendpid = 0;

  reset_terminal_state();    /* give original terminal characters */
  set_caller_ttystate();

  

  close_files();
  close_terminal();

  if (DEBUG_SIGNAL) 
    print_error2(P_DEBUG,"Exit  ...");
                
  kill(mypid,SIGTERM);          /* Kill me */
  exit(6);

}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]