[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:
http://bugs.kde.org/show_bug.cgi?id=164540
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. ()
Loc:
[/usr/ports/x11/kdelibs4/work/kdelibs-4.0.83/kpty/tests/kptyprocesstest.cpp(76)]
-----------------------------------------------------------------------------------------------------------------------
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()
{
Q_Q(KPtyDevice);
qint64 readBytes = 0;
#ifdef Q_OS_IRIX // this should use a config define, but how to check it?
size_t available;
#else
int available;
#endif
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
http://www.pcbsd.com
More information about the kde-freebsd
mailing list