[kde-freebsd] Konsole / kpty porting (long)

Kris Moore kris at pcbsd.com
Wed Jul 9 15:58:49 CEST 2008

Hey everybody! I've tried taking a stab at the fixing of kpty on BSD, so 
we can use Konsole among other things. I've been able to identify where 
I think the problems are occurring, but haven't been able to figure out 
a fix to it yet, since it delves a bit deeper into ioctl, and other 
system calls than I am familiar with. I figure I will post my notes 
here, with a walkthrough of how I got to where I am, and see if that 
helps anybody else in fixing this bug. Sorry if this post is a bit long, 
I don't want to leave any details out.

First, I started by creating the kptyprocesstest program, which helps us 
figure out why kpty is broken:

# cd /usr/ports/x11/kdelibs4/
# make

Now CD to the build dir, and create the processtest program:
# cd work/kdelibs*/build/kpty/tests
# make kptyprocesstest

Now run the test program:
# ./kpryprocesstest.shell

When you run the test, you will see quite a few failures, which you can 
see a full example of here:

I was able to zero in on this test specifically, and I'm 95% positive 
that it is causing ALL of the failures:
FAIL!  : KPtyProcessTest::test_shared_pty() 
'p.pty()->waitForReadyRead(1000)' returned FALSE. ()

I then started going through the kpty code, and placed in markers until 
I was able to determine where the failure was occurring exactly, in the 
kpty/kptydevice.cpp file, specifically this function:


bool KPtyDevicePrivate::_k_canRead()
     qint64 readBytes = 0;

#ifdef Q_OS_IRIX // this should use a config define, but how to check it?
     size_t available;
     int available;
     if (!::ioctl(q->masterFd(), FIONREAD, (char *) &available)) {
         char *ptr = readBuffer.reserve(available);
         NO_INTR(readBytes, read(q->masterFd(), ptr, available));
         if (readBytes < 0) {
             q->setErrorString(I18N_NOOP("Error reading from PTY"));
             return false;
         readBuffer.unreserve(available - readBytes); // *should* be a no-op

........................ cut .......................


The failure speficially is happening with the "ioctl" line here:

if (!::ioctl(q->masterFd(), FIONREAD, (char *) &available)) {

ioctl keeps returning -1 and setting errno to 35, which is this:
#define EAGAIN          35              /* Resource temporarily 
unavailable */

Now that isn't the only intersting thing, if I ignore the ioctl error, 
and set available=10 or something, the next line:

NO_INTR(readBytes, read(q->masterFd(), ptr, available));

Will *attempt* to read the output from our pty, and on some of the test 
cases, this fixes it. However, for the most critical ones, which attempt 
to interact with a shell, there is still no data available on the Fd / 
pty. This makes me think that somewhere the pty session *isn't* being 
setup properly, in order to make read data available. The ioctl could be 
working perfectly fine, and it is detecting that there isn't data 
available, or that it is bad somehow.

Thats about as far as I gotten after a several hours of fiddling with 
it. The write portion of the kpty code seems to work perfectly, and I 
was able to do a few simulations to confirm this. Its only reading it 
back that causes trouble. Its possible that the error is occurring in 
the kpty.cpp code instead, since that is where we have some 
system-specific code which uses openpty and starts the process at first.

Anybody else have any thoughts on there, or figure something else out to 
fix this?


Kris Moore
PC-BSD Software

More information about the kde-freebsd mailing list