Crash test

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

 



Hi All,

I have been haunted by a problem with SMP kernels since 2.4.1. I have an
application program that causes dual processor kernels or Pentium MT
kernels to crash. I have tried to find the cause myself but have not been
succesful in that.

The (original) application does basically:

Open a serial port / write a few bytes / toggle RTS / read a few bytes /
close port.

It does it up to twice a second. There may however arrive bytes while
closing the port.

Attached is a program that demonstrates it. I tried it and yes, my

Linux version 2.4.31 (root@merin) (gcc version 3.3.5 (Debian 1:3.3.5-13)) #1
SMP Tue Oct 25 12:31:57 CEST 2005

crashed within 10 minutes :-((((((((

It locks up totally.

I found that 2.6 kernels will crash (at least with the original application)
too.

The serial input data is to be 'simulated' with a square wave generator on
the com port input.

You need a frequency generator of about 1300 Hertz to set the test up.

I have never been able to catch the underlying bug myself. It is probabely a
race problem somewhere in the interrupt allocation/de-allocation part..

I hope that someone with a spare SMP system (my SMP system is my
workstation at work, so I don't like the crashes at all) can try this and
catch the bug.

kind regards

Kees
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <termio.h> 
#include <unistd.h>
#include <sys/poll.h>
#include <signal.h>


/* this test program seeks to demonstrate a (longstanding) problem in
 * 2.4 and 2.6 SMP kernels.
 * The original application that is hindered by the problem is different
 * but this demo program contains enough aspects that it will crash a 
 * SMP linux system soon. My experience is between almost direct to about 30 minutes.
 * 
 * I have been able to immuminize only the 2.4.4 kernel. The same patch on later kernels did 
 * not help any longer.
 *
 * in order to test it apply a square wave generator to a serial port i.e.
 * /dev/ttyS0, I tested with +/ 2.5 Volts and 1300 Hertz. This produces a '?' character 
 * if the port is read with
 * (stty 1200 cs8 </dev/ttyS0 ; cat /dev/ttyS0)
 *
 * +----------------+
 * |                | signal            -----------
 * | 1.3 kHz        |-------------------| 470 Ohm |-----------------  pin 3 serial connector
 * |                |                   -----------
 * | +/- 2.5 Volts  |
 * | square wave    | ground
 * |                |-----------------------------------------------  pin 7 serial connector
 * +----------------+
 *
 * 
 * the test program can be run with
 *
 * crash_test -H /dev/ttyS0 (assuming that this is the correct port)
 *
 * the -S option disables the consequetive opening and closing of the port, if this option 
 * is applied, NO crash follows.
 * 
 * kees schoenmakers [email protected] / [email protected]
 * 
 */


int test_open(), read_char(); 
void test_nrts(), test_close();
int smp_opt=0;

struct termio tio;
struct pollfd testfd;

unsigned char tbuf[32];


int main(argc, argv )
int argc;
char **argv;
{
	char c;
	int i;
	char *portname="";

	 while (( c= getopt(argc, argv, "SH:")) != -1){
		     switch (c) {
					case 'H':
										portname=optarg;
										break;

					case 'S':
										smp_opt++;
										break;
	          exit(1);
		    }
	  }

	testfd.fd = -1;
	testfd.events= 0 |POLLIN;
	
  sprintf((char *)&tbuf, "test\n");
	

	signal( SIGFPE, SIG_IGN);

	if( !strlen(portname)){
		if((portname = getenv("TEST_PORT")) == NULL){
			fprintf(stderr,"Port unknown, set TEST_PORT\n");
			exit(1);
		}
	}

	while(1){ 							/* main loop this does it !! */

		if( test_open( portname) < 0)
			exit(-2);

		write(testfd.fd, (char *) &tbuf, strlen (tbuf));
		
		test_nrts();
		
		for( i =0 ; i < 6 ; i++){
			read_char(testfd.fd);
		}

		test_close();
		
		usleep(10000);
	} /* 'main' while */
}

int test_open(portname)
char *portname;
{
extern int errno;

	if( testfd.fd == -1){
		if((testfd.fd = open(portname , O_RDWR)) < 0){
			printf("*** can't open %s port, error %d \n",portname, errno);
			testfd.fd = -1;
			return (-1);
		}
		ioctl(testfd.fd , TCGETA, &tio);
		tio.c_cflag = CS8 | B1200 | CREAD | CLOCAL;
		tio.c_iflag = IGNBRK;
		tio.c_lflag = 0;
		tio.c_oflag = 0;
		tio.c_cc[4] = 1;
		tio.c_cc[5] = 1;
		ioctl(testfd.fd , TCSETA, &tio);
	}
	return(0);
}

/* switch from xmit to receive, toggle RTS line */

void test_nrts()
{
int parm;
		usleep(1000);	/* wait for buffer to drain */
		while(1){
			ioctl(testfd.fd, TIOCSERGETLSR, &parm);
			if (parm)
				break;
		}
		ioctl(testfd.fd, TIOCMGET, &parm);
		parm &= ~TIOCM_RTS; /* RTS off */
		ioctl(testfd.fd, TIOCMSET, &parm );
		return;
}

void test_close()
{
	int parm;

	if(!smp_opt){  /* normally close the port */
	if( testfd.fd >=0)
		close( testfd.fd);
	testfd.fd = -1;
	} else {
		usleep(1000);	
		/* put RTS back on */
		ioctl(testfd.fd, TIOCMGET, &parm);
		parm |= TIOCM_RTS; /* RTS on */
		ioctl(testfd.fd, TIOCMSET, &parm );
	}
}

int read_char()
{
   unsigned char c;
	 int r_stat;

   r_stat=poll(&testfd, 1, 10);
   if(r_stat > 0) 
      read(testfd.fd, &c, 1);
	 return (int) c;
}


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux