On Thursday 01 January 2009 21:33:34 Petter Reinholdtsen wrote: > Here is a patch I wrote a year ago to work around the getpt() problem. > It uses a copy of the glibc getpt() function until /dev/pts is > mounted, this working around the fact that the glibc getpt() only > probe once if /dev/pts exist.
Did you receive feedback about it? I notice it has not been applied to startpar version 0.52. > > ----- Forwarded message from Petter Reinholdtsen <[email protected]> ----- > > Date: Thu, 28 Feb 2008 12:21:16 +0100 > From: Petter Reinholdtsen <[email protected]> > To: Stephan Kulow > Cc: "Dr. Werner Fink" > Subject: Re: Using startpar in makefile mode and failing getpt() > > [Stephan Kulow] > > /etc/init.d/boot is the script executed by inittab and this one will > > mount important file systems before calling startpar. boot.localfs > > will remount them later. > > Aha. That explains it. I try to work around it by replacing getpt(). > The version in glibc will only check once if the required files and > partitions are present, and refuse to check again when the environment > change while the process is running. My replacement do not have that > problem. > > I've had to patch startpar a bit to get it working on Debian, and here > is the complete patch, relative to version 0.50. > > - I had to change the path used to find the rc*.d/ directories. > - I added debug modus to get more output while figuring out what is > wrong > - I added the getpt() hack. Currently protected using an #ifdef to > be able to test without it. Do you think it is important to protect this hack with #ifdef's ? > > When I test startpar in makefile mode with debugging enabled and the > getpt() hack disabled, it try to run the same scripts several times. > When processing rc2.d/ (skipped rcS.d/ because of the getpt() > problem), it try to run rc.local three times, and both stop-bootlogd > and sysklogd twice. Any idea why this happen? Is the same problem > present on SuSe when printing debug output? I have separate patches to make startpar (seemingly, for me) work nicely with Debian rc.d design. It does not suffer from duplicate execution of scripts as far as I can tell. Below is patch based on yours for startpar 0.52. Thanks, Kel. --- --- a/startpar.c +++ b/startpar.c @@ -31,6 +31,7 @@ #include <sys/ioctl.h> #include <sys/sysinfo.h> #include <sys/stat.h> +#include <sys/vfs.h> #include <time.h> #include <fcntl.h> #include <errno.h> @@ -271,6 +272,62 @@ static inline int checkpar(const int par return checksystem(par, start, false); } +/* + * Based on __posix_openpt() from glibc. Reimplemented here to work + * around the problem with getpt() failing for the entire process life + * time if /dev/pts/ is missing the first time it is called but + * mounted while the process is running. BSD style pts is not + * supported, but might be copied from glibc too if there is need. + */ +#define DEVFS_SUPER_MAGIC 0x1373 +#define DEVPTS_SUPER_MAGIC 0x1cd1 + +static int startpar_getpt(void) { + int fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); + + if (fd != -1) + { + struct statfs fsbuf; + + /* Check that the /dev/pts filesystem is mounted + or if /dev is a devfs filesystem (this implies /dev/pts). */ + if ((statfs ("/dev/pts", &fsbuf) == 0 + && fsbuf.f_type == DEVPTS_SUPER_MAGIC) + || (statfs ("/dev", &fsbuf) == 0 + && fsbuf.f_type == DEVFS_SUPER_MAGIC)) + { + /* Everything is ok, switch to the getpt() in libc. */ + return fd; + } + + /* If /dev/pts is not mounted then the UNIX98 pseudo terminals + are not usable. */ + close (fd); + } + + return -1; +} + +static int checkdevpts(void) +{ + int ptsfd = startpar_getpt(); + + if (ptsfd == -1) + { + return 0; + } + else if (ptsname(ptsfd) == 0 || grantpt(ptsfd) || unlockpt(ptsfd)) + { + close(ptsfd); + return 0; + } + else + { + close(ptsfd); + return 1; + } +} + void run(struct prg *p) { char *m = 0; @@ -775,6 +832,7 @@ int main(int argc, char **argv) pid_t pid = 0; int r = 0, s; long diff; + int devpts = 0; gettimeofday(&now, 0); FD_ZERO(&rset); @@ -796,6 +854,8 @@ int main(int argc, char **argv) for (s = 0; s < par; s++) /* never leave this with break!! */ { account: /* for the new process below */ + if (!devpts) + devpts = checkdevpts(); p = prgs + s; if (p == interactive_task) continue; /* don't count this here */ @@ -815,7 +875,7 @@ int main(int argc, char **argv) { if ((nodevec[num] = pickup_task()) == NULL) continue; - if (nodevec[num]->interactive) + if (nodevec[num]->interactive || !devpts) interactive_task = p; p->name = nodevec[num]->name; } --- -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected]

