[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MINTOS: Porting Library !?
Micheal Hohmuth writes:
> Rather, we should concentrate on things that have to be generalized
> in order to reach a state where Unix software con be compiled out of
> the box.
Yes, I would love that state, too. But obviously there are some problems,
which cannot be solved transparently in the library without changing the
MiNT kernel. Probably everyone who ever ported unix software to MiNT came
across those things.
I think we should try to find general solutions for those problems which
require only minimal changes to the source code (ie no mayor rewrites).
Any other opinions, I think not :-).
So I'm going to start a list of what I call 'elegant solutions' to some
of the above problems. Probably there are lots of such 'workarounds' out
there. It would be great to have a look at and collect them.
Perhaps we could even build a nonstandart library containing useful code
for porting unix software.
Here are my suggestions:
(1) Mint's fork() blocks the parent until the child exec()'s or
exit()'s. This is a problem in constructs like:
if (!fork()) exit();
Here is a workaround, which uses tfork() and requires only
minimal changes to the source. Using tfork() directly often
requires restructuring of the source.
------------------------ cut ----------------------------
#include <unistd.h>
#include <fcntl.h>
#include <ioctl.h>
#include <setjmp.h>
#include <signal.h>
static int fd_flags[32];
static jmp_buf jmpbuf;
static long sigmask;
static struct sigaction sigacts[32];
int
child_proc (long pip)
{
char buf;
int i;
sigsetmask (~0L);
if (read (pip, &buf, 1)) exit (0);
close (pip);
for (i = 0; i < 32; ++i) {
if (fd_flags[i] >= 0)
fcntl (i, F_SETFD, fd_flags[i]);
}
for (i = 0; i < 32; ++i) {
sigaction (i, &sigacts[i], 0);
}
longjmp (jmpbuf, 1);
}
int
__fork_and_exit (void)
{
int i, pip[2];
sigmask = sigsetmask (~0L);
if (pipe (pip) < 0) return -1;
for (i = 0; i < 32; ++i) {
fd_flags[i] = fcntl (i, F_GETFD, 0);
fcntl (i, F_SETFD, i == pip[1] ? FD_CLOEXEC : 0);
}
for (i = 0; i < 32; ++i) {
sigaction (i, 0, &sigacts[i]);
}
if (!setjmp (jmpbuf)) {
/* parent */
tfork (child_proc, pip[0]);
exit (0);
}
/* child */
sigsetmask (sigmask);
return 0;
}
--------------------------- cut ----------------------------
__fork_and_exit() preserves file handles, signal handlers
and the set of masked signals to the child, much like fork()
does.
Its functionlity is the same as for if (!fork()) exit().
(2) Another problem is that Mint/MintLibs read()/write() have
no POSIX nonblocking mode (activated with the O_NONBLOCK
fcntl()) flags. The difference to O_NDELAY nonblocking mode
is that read()/write() return -1 and EWOULDBLOCK/EAGAIN in
errno if no data/space is available at all (instead of
returning 0 when O_NDELAY is actice).
I know Entropy worked on this, but in the MintLibs this stuff
is commented out.
My solution is probably not more than a hack. Improvements
are appreciated.
-------------------------- cut -------------------------------
#include <fcntl.h>
#include <errno.h>
#include <ioctl.h>
#include <osbind.h>
#include <mintbind.h>
#define UNLIMITED 1000000000L
int
__posixish_read (int fd, void *buffer, unsigned int buflen)
{
int r, s;
unsigned long buf;
extern int errno;
r = Fread (fd, buflen, buffer);
if (r <= 0) {
if (r < 0) {
errno = -r;
return -1;
}
if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
s = Fcntl (fd, &buf, FIONREAD);
if (!s && buf < UNLIMITED) {
errno = EWOULDBLOCK;
return -1;
}
}
}
return r;
}
int
__posixish_write (int fd, void *buffer, unsigned int buflen)
{
int r, s;
unsigned long buf;
extern int errno;
r = Fwrite (fd, buflen, buffer);
if (r <= 0) {
if (r < 0) {
errno = -r;
return -1;
}
if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
s = Fcntl (fd, &buf, FIONWRITE);
if (!s && buf < UNLIMITED) {
errno = EWOULDBLOCK;
return -1;
}
}
}
return r;
}
------------------------- cut -----------------------------------
When only O_NONBLOCK nonblocking mode is used, you could
then
#define read(a,b,c) __posixish_read(a,b,c)
#define write(a,b,c) __posixish_write(a,b,c)
#define O_NONBLOCK O_NDELAY
and use this as a reasonabe emulation.
(3) select()ing for exceptional conditions does not work.
This is a pitty for sockets (TCP) and out of band data.
Perhaps we could do a workaround using SIGURG.
Any suggestions?
Waiting for your opinion and suggestions,
Kay.