[ROOT] Possible unintended behaviour in TSystemDirectory::GetListOfFiles()

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Mon Dec 16 2002 - 20:51:03 MET


Hi. 

After a rather odd problem arouse in some client code, I found that 
`TSystemDirectory::GetListOfFiles()' may have an unintended (or at
unexpected) behaviour.  Hence, I'd like to alert you all to this
`thingy' (bug, feature, ...).  This applies to Unix systems (those
that makes `gSystem' and instance of `TUnixSystem'). 

* First you create an object of class `TSystemDirectory'

* Then, when you do `TSystemDirectory::GetListOfFiles()' the directory
  is opened via `TSystem::OpenDirectory', and later closed via
  `TSystemDirectory::FreeDirectory'. 

* `TSystem::OpenDirectory' is a virtual member function, so the real
  member function executed is `TUnixSystem::OpenDirectory' which
  dispatches to `TUnixSystem::UnixOpendir'.  

* Likewise, `TSystemDirectory::FreeDirectory' is virtual, and the real
  member function called is `TUnixSystem::FreeDirectory' which
  dispatches to `TUnixSystem::UnixClosedir'.  

* `TUnixSystem::UnixOpendir' calls `opendir' (from the C library),
  which sets the working directory to the directory you're scanning.  

* `TUnixSystem::UnixClosedir' calls `closedir' (from the C library), 
  but the working directory _isn't_restored_ to the old working
  directory. 

Now, this also means, that when you browse a directory in the
`TBrowser', the `working directory' is set to that directory - which
in turn may effects the script loading, library loading, and so on,
assuming you have `.' in your script and/or library load path
(probably not a good idea in the first place). 

This was seen on Red Hat 7.3 at least. I'm not sure what the ISO and
POSIX standards say `opendir' and `closedir' should do in terms of
`working directory'.   

If that's not the intended behaviour, the fix is to do 

   TList *TSystemDirectory::GetListOfFiles() const
   {
      ...
>     TString oldwd(gSystem->WorkingDirectory()); 
      void *dir = gSystem->OpenDirectory(GetTitle());
      if (!dir) return 0;

      const char *file = 0;
      ...
      gSystem->FreeDirectory(dir);
>     gSystem->ChangeDirectory(oldwd.Data());
      return contents;
  }

[New lines marked with `>' in column 0]

Perhaps the `TSystem::OpenDirectory' could push a reference to
the old working directory onto a stack, and `TSystem::FreeDirectory' 
could pop it.  In that way, it'd be easy to do 

  gSystem->ChangeDirectory("-")

much like in the shell. 

Anyway - I thought you should at least be alerted as to this
side-effect. 

Oh, and I'd like to take this opportunity to direct your attention to
the Debian GNU/Linux 3.0r0 packages of ROOT 3.03/09 available from
[1].  

Yours, 

 ___  |  Christian Holm Christensen 
  |_| |	 -------------------------------------------------------------
    | |	 Address: Sankt Hansgade 23, 1. th.  Phone:  (+45) 35 35 96 91
     _|	          DK-2200 Copenhagen N       Cell:   (+45) 24 61 85 91
    _|	          Denmark                    Office: (+45) 353  25 305
 ____|	 Email:   cholm@nbi.dk               Web:    www.nbi.dk/~cholm
 | |

[1] http://cholm.home.cern.ch/cholm/root 



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:23 MET