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

[cause] Re: logout kills X




The crash happens due to a race condition in switching forth and back
using:

 ioctl(fd,VT_ACTIVATE,  tmp_tty)
 ioctl(fd,VT_WAITACTIVE,tmp_tty)
                                <- here
 ioctl(fd,VT_ACTIVATE,  org_tty)
 ioctl(fd,VT_WAITACTIVE,org_tty)

in clear_console.c's clear_console() function.
https://launchpad.net/ubuntu/+source/bash/5.0-2ubuntu1


Being offline, I couldn't check this code directly. However I wrote a
demo that mostly constitutes the clear_console() function in
clear_console.c (link above).


course:

startx on tty1
start demo on tty2
-> get an unresponsive but still running X session

however:
blindly typing: chvt 3
brings me back to tty3
(chvt 2 would do nothing, while the system thinks it's always where)

also:
[alt]+[F3] brings me back to tty3

then:
switching to tty1, whatever how, X realizes something went wrong and
crashes.



If I put sleep(1) inbetween (at the here marker) everything is fine
(you know what I mean). Henceforth and because of the input/output
split (schizophrenia) X session, I guess, this is a race condition and
at this point (missing debugging skills) I'm out.



Demo:

// gcc -Wall <whatever-you-name-it>.c

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include <linux/vt.h>


int
main() {

  char* file = "/dev/tty";  // arbitrary choosing the one that works
  int   fd   = open( file,O_RDWR );
  if( fd<0 && errno==EACCES) {
    printf("(E) open file: %s\n",file);
    return 1;
    }
  printf(":: fd: %d\n",fd);

  /* get current vt */
  int num;
  int tmp_num;
  struct vt_stat vtstat;
  if( ioctl(fd,VT_GETSTATE,&vtstat ) < 0 ) {
    fprintf(stderr, "console2: cannot get VTstate\n");
    exit(1);
    }
  num     = vtstat.v_active;    // current
  tmp_num = (num==1 ? 2 : 1);   // temporary


  fprintf(stderr, "vt_stat.v_active: %d\n",num);
  fprintf(stderr, "tmp_num: %d\n",tmp_num);
  fprintf(stderr, "console2: switching VTs\n");


  // switch forth  (this cuts scrollback buffer)
  if( ioctl(fd,VT_ACTIVATE,tmp_num) ) {
    perror("chvt: VT_ACTIVATE");
    exit(1);
    }

  if( ioctl(fd,VT_WAITACTIVE,tmp_num) ) {
    perror("VT_WAITACTIVE");
    exit(1);
    }

//  sleep(1);

  // switch back
  if( ioctl(fd,VT_ACTIVATE,num) ) {
    perror("chvt: VT_ACTIVATE");
    exit(1);
    }

  if( ioctl(fd,VT_WAITACTIVE,num) ) {
    perror("VT_WAITACTIVE");
    exit(1);
    }

  return 0;
  }


Reply to: