[Pkg-sysvinit-devel] Bug#457896: Bug#457896: (fwd) Re: Using startpar in makefile mode and failing getpt()
Kel Modderman
kel at otaku42.de
Sun Jan 4 14:29:38 UTC 2009
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 <pere at hungry.com> -----
>
> Date: Thu, 28 Feb 2008 12:21:16 +0100
> From: Petter Reinholdtsen <pere at hungry.com>
> 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;
}
---
More information about the Pkg-sysvinit-devel
mailing list