Hi Petter and Steve,

On Monday 18 August 2008 16:46:08 Petter Reinholdtsen wrote:
> [Steve Langasek]
> > In this case, NFS...
> 
> Right.  So ext3 and NFS should be ok. :)
> 
> > I can try against a different filesystem tomorrow if you like.
> 
> If you happen to know what file system is used on the autobuilder, or
> if ext2/ext3 is not the default file system on alpha, it would be
> useful to have a test with those file systems as well.  If not, it
> will be a shot in the dark, and I have no idea what file system to
> suggest.

I think insserv can handle this situation without disabling optimisations, the
problem seems to concern the use of an underterministic directory sequence,
as returned by a while readdir() loop, when scanning the init.d/ directory to
load LSB init info.

The fact that the problem was discovered with a symlink test, is I think
interesting, but not neccessarily an indication of some lower level problem
with kernel / filesystem interaction. The problem can be reproduced with a more
simple test too:
---
test_deterministic_order() {
echo
echo "info: test two or more initscripts providing same facility, making sure"
echo "info: that the first script can be registered with insserv, but others 
fail." 
echo

initdir_purge

addscript abc <<'EOF' || true
### BEGIN INIT INFO
# Provides:          service
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
### END INIT INFO
EOF

addscript xyz <<'EOF' || true
### BEGIN INIT INFO
# Provides:          service
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
### END INIT INFO
EOF

addscript hjk <<'EOF' || true
### BEGIN INIT INFO
# Provides:          service
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
### END INIT INFO
EOF

insserv_reg xyz || true
insserv_reg hjk || true
insserv_reg abc || true

list_rclinks

check_script_present S xyz
check_script_not_present S abc
check_script_not_present S hjk
}
---
The above test will always fail, but differently when run on different 
filesystems
(eg. ext3 vs tmpfs). It seems the information that readdir(3) returns from a
filesystem is not always the same.

insserv could defend against this behaviour, by ensuring that the script being
registered is parsed first, followed by all other scripts. I've put together a
hack to do just that, it is attached. WIll commit it to the packaging SVN with
test case for further discussions.

Thanks, Kel.
---
--- a/insserv.c
+++ b/insserv.c
@@ -2238,6 +2238,7 @@
     boolean del = false;
     boolean defaults = false;
     boolean ignore = false;
+    boolean loadarg = argc;
 
     myname = basename(*argv);
 
@@ -2490,17 +2491,45 @@
     /*
      * Scan now all scripts found in the init.d/ directory
      */
-    while ((d = readdir(initdir)) != (struct dirent*)0) {
-       const boolean isarg = chkfor(d->d_name, argv, argc);
+    for (;;) {
        service_t * service = (service_t*)0;
        char * token;
        char * begin = (char*)0;        /* hold start pointer of strings 
handled by strsep() */
        boolean hard = false;
+       boolean isarg = false;
        uchar lsb = 0;
 #if defined(DEBUG) && (DEBUG > 0)
        int nobug = 0;
 #endif
 
+       if ((d = readdir(initdir)) == (struct dirent*)0) {
+           /*
+            * If first script in argument list was loaded in advance, then
+            * rewind the init.d/ directory stream and attempt to load all
+            * other scripts.
+            */
+           if (loadarg) {
+               loadarg = false;
+               rewinddir(initdir);
+               continue;
+           }
+           break;
+       }
+
+       isarg = chkfor(d->d_name, argv, argc);
+
+       /*
+        * Load first script in argument list before all other scripts. This
+        * avoids problems with loading services in underterministic sequence
+        * returned by readdir(3).
+        */
+       if (loadarg && !isarg)
+           continue;
+       else if (loadarg  && isarg && (curr_argc != 0))
+           continue;
+       else if (!loadarg && isarg && (curr_argc == 0))
+           continue;
+
        if (*d->d_name == '.')
            continue;
        errno = 0;
---



-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to