Subject: kern/3354: SVR4 compat doesn't set O_ASYNC for ioctl(_, I_SETSIG, _)
To: None <gnats-bugs@gnats.netbsd.org>
From: Michael Eriksson T/D <Michael.Eriksson@era-t.ericsson.se>
List: netbsd-bugs
Date: 03/18/1997 18:54:32
>Number:         3354
>Category:       kern
>Synopsis:       SVR4 compat doesn't set O_ASYNC for ioctl(_, I_SETSIG, _)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Mar 18 10:05:03 1997
>Last-Modified:
>Originator:     Michael Eriksson
>Organization:
Ericsson Radio Systems AB
>Release:        1.2
>Environment:
NetBSD 1.2 + some parts from later -current on sparc (Sun IPX).
>Description:

When the SVR4 compatibility mode emulates ioctl(_, I_SETSIG, _), it
only does the equivalent of fcntl(_, F_SETOWN, _), and misses to set
the O_ASYNC flag (i.e., fcntl(_, F_SETFL, O_ASYNC)). This means that
the emulated process never will get any SIGPOLLs.

This is what's been hindering (on my machine anyway) Sun's Java
implementation for Solaris to get any windows on the screen under
NetBSD/sparc. (It's waiting forever for the SIGPOLLs that should tell
it that there's data from the X server.)

Because of the interest in Java, I've set the priority of the PR to
medium, even though the severity is low. (It's kinda neat to run the
Solaris JDK under NetBSD. :-))

>How-To-Repeat:

Try to run the Solaris JDK under NetBSD/sparc, and watch it hang in
sigpause without having put any windows on the screen.

>Fix:

Here are patches against my semi-current version of sys/compat/svr4.
It should be trivial to adjust them to the latest sources.

I've removed the handling of the SVR4_O_RAOSIG flag, which seems to
somehow be the equivalent of BSD's O_ASYNC. Solaris (i.e. SunOS 5)
doesn't use it, and none of the books I have (_The Magic Garden
Explained_ by Goodheart & Cox and _Advanced Programming in the UNIX
Environment_ by Stevens) mention it either. Both the books say that
your supposed to use ioctl(_, I_SETSIG, _) to get SIGPOLL
functionality (and nothing about any fcntl() calls), so I really don't
know where the O_RAIOSIG stuff is coming from. Maybe it's a Xenix
thing. I don't have access to any vanilla SVR4 systems to check it,
though.



*** svr4_fcntl.c.orig	Tue Mar 18 18:20:22 1997
--- svr4_fcntl.c	Tue Mar 18 18:21:34 1997
***************
*** 94,100 ****
  	r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
  	r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
  	r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
- 	r |= (l & SVR4_O_RAIOSIG) ? O_ASYNC : 0;
  	r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
  	r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
  	r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
--- 94,99 ----
***************
*** 116,122 ****
  	r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
  	r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
  	r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
- 	r |= (l & O_ASYNC) ? SVR4_O_RAIOSIG : 0;
  	r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
  	r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
  	r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
--- 115,120 ----
***************
*** 283,291 ****
  		return error;
  
  	case F_SETFL:
! 		SCARG(&fa, arg) =
! 			(void *) svr4_to_bsd_flags((u_long) SCARG(uap, arg));
! 		return sys_fcntl(p, &fa, retval);
  
  	case F_GETLK:
  	case F_SETLK:
--- 281,304 ----
  		return error;
  
  	case F_SETFL:
! 		{
! 			/*
! 			 * we must save the O_ASYNC flag, as that is
! 			 * handled by ioctl(_, I_SETSIG, _) emulation.
! 			 */
! 			int cmd, flags;
! 
! 			cmd = SCARG(&fa, cmd); /* save it for a while */
! 
! 			SCARG(&fa, cmd) = F_GETFL;
! 			if ((error = sys_fcntl(p, &fa, &flags)) != 0)
! 				return error;
! 			flags &= O_ASYNC;
! 			flags |= svr4_to_bsd_flags((u_long) SCARG(uap, arg));
! 			SCARG(&fa, cmd) = cmd;
! 			SCARG(&fa, arg) = (void *) flags;
! 			return sys_fcntl(p, &fa, retval);
! 		}
  
  	case F_GETLK:
  	case F_SETLK:
*** svr4_fcntl.h.orig	Tue Mar 18 18:20:22 1997
--- svr4_fcntl.h	Tue Mar 18 18:21:34 1997
***************
*** 40,46 ****
  #define	SVR4_O_NDELAY		0x0004
  #define	SVR4_O_APPEND		0x0008
  #define	SVR4_O_SYNC		0x0010
- #define SVR4_O_RAIOSIG		0x0020
  #define	SVR4_O_NONBLOCK		0x0080
  #define	SVR4_O_CREAT		0x0100
  #define	SVR4_O_TRUNC		0x0200
--- 40,45 ----
*** svr4_stream.c.orig	Tue Mar 18 18:20:22 1997
--- svr4_stream.c	Tue Mar 18 18:21:34 1997
***************
*** 1229,1243 ****
  		/* 
  		 * This is the best we can do for now; we cannot generate
  		 * signals only for specific events so the signal mask gets
! 		 * ignored
! 		 */
  		{
  			struct sys_fcntl_args fa;
  
  			SCARG(&fa, fd) = fd;
! 			SCARG(&fa, cmd) = F_SETOWN;
! 			SCARG(&fa, arg) = (void *) p->p_pid;
! 			return sys_fcntl(p, &fa, retval);
  		}
  
  	case SVR4_I_GETSIG:
--- 1229,1269 ----
  		/* 
  		 * This is the best we can do for now; we cannot generate
  		 * signals only for specific events so the signal mask gets
! 		 * ignored.
! 		 *
! 		 * We alse have to fix the O_ASYNC fcntl bit, so the
! 		 * process will get SIGPOLLs. */
  		{
  			struct sys_fcntl_args fa;
+ 			int error;
+ 			register_t oflags, flags;
  
+ 			/* get old status flags */
  			SCARG(&fa, fd) = fd;
! 			SCARG(&fa, cmd) = F_GETFL;
! 			if ((error = sys_fcntl(p, &fa, &oflags)) != 0)
! 				return error;
! 
! 			/* update the flags */
! 			if ((long) dat != 0)
! 				flags = oflags | O_ASYNC;
! 			else
! 				flags = oflags & ~O_ASYNC;
! 
! 			/* set the new flags, if changed */
! 			if (flags != oflags) {
! 				SCARG(&fa, cmd) = F_SETFL;
! 				SCARG(&fa, arg) = (void *) flags;
! 				if ((error = sys_fcntl(p, &fa, &flags)) != 0)
! 					return error;
! 			}
! 
! 			/* set up SIGIO receiver if needed */
! 			if ((long) dat != 0) {
! 				SCARG(&fa, cmd) = F_SETOWN;
! 				SCARG(&fa, arg) = (void *) p->p_pid;
! 				return sys_fcntl(p, &fa, retval);
! 			}
  		}
  
  	case SVR4_I_GETSIG:

>Audit-Trail:
>Unformatted: