Browse Source

Patched problem with too many files: invoke GC followed by waiting for files to close

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6984 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 years ago
parent
commit
6bc1225108
2 changed files with 46 additions and 13 deletions
  1. 45 12
      source/Generic.Unix.UnixFiles.Mod
  2. 1 1
      source/StdIOShell.Mod

+ 45 - 12
source/Generic.Unix.UnixFiles.Mod

@@ -20,7 +20,7 @@ CONST
 	Trace = {};
 	Trace = {};
 VAR
 VAR
 	tempno: INTEGER;
 	tempno: INTEGER;
-	openfiles: INTEGER;
+	openfiles: LONGINT;
 	
 	
 	searchPath: ARRAY 1024 OF CHAR;
 	searchPath: ARRAY 1024 OF CHAR;
 	cwd: ARRAY 256 OF CHAR;
 	cwd: ARRAY 256 OF CHAR;
@@ -243,7 +243,7 @@ TYPE
 
 
 				PROCEDURE Old0*( name: ARRAY OF CHAR ): Files.File;
 				PROCEDURE Old0*( name: ARRAY OF CHAR ): Files.File;
 				VAR f: File;  stat: Unix.Status;  fd, r, errno, pos: LONGINT;
 				VAR f: File;  stat: Unix.Status;  fd, r, errno, pos: LONGINT;
-					oflags: SET;  nextdir, path: Filename; 
+					oflags: SET;  nextdir, path: Filename;  fo: LONGINT;
 				BEGIN  {EXCLUSIVE}
 				BEGIN  {EXCLUSIVE}
 					IF name = "" THEN  RETURN NIL  END;
 					IF name = "" THEN  RETURN NIL  END;
 					
 					
@@ -265,8 +265,13 @@ TYPE
 							fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
 							fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
 							IF ((fd < 0) & (errno IN {Unix.ENFILE, Unix.EMFILE})) (* OR (fd >= FileTabSize)*)  THEN
 							IF ((fd < 0) & (errno IN {Unix.ENFILE, Unix.EMFILE})) (* OR (fd >= FileTabSize)*)  THEN
 								(*IF fd > 0 THEN  r := Unix.p( fd )  END;*)
 								(*IF fd > 0 THEN  r := Unix.p( fd )  END;*)
-								(*!GC ;*)
-								fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
+								REPEAT
+									TRACE(errno, openfiles);
+									fo := openfiles;
+									Kernel.GC;
+									WaitClose(fo);
+									fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
+								UNTIL (fd >= 0) OR ~ (errno IN  {Unix.ENFILE, Unix.EMFILE})
 							END;
 							END;
 
 
 							IF fd >= 0 THEN
 							IF fd >= 0 THEN
@@ -292,7 +297,7 @@ TYPE
 									END;
 									END;
 									f.key := NoKey;  f.fs := SELF;
 									f.key := NoKey;  f.fs := SELF;
 									(*fileTab[fd].f := f;  (* cache file *)*)
 									(*fileTab[fd].f := f;  (* cache file *)*)
-									INC( openfiles );  
+									IncOpenFiles();
 									collection.AddOld(f);
 									collection.AddOld(f);
 									(*RegisterFinalizer( f, Cleanup );*)
 									(*RegisterFinalizer( f, Cleanup );*)
 									EXIT
 									EXIT
@@ -515,7 +520,7 @@ TYPE
 
 
 				PROCEDURE CreateUnixFile;
 				PROCEDURE CreateUnixFile;
 				VAR 
 				VAR 
-					stat: Unix.Status;  done: BOOLEAN;  r: LONGINT;
+					stat: Unix.Status;  done: BOOLEAN;  errno,fo: LONGINT;
 				BEGIN
 				BEGIN
 					IF state = Create THEN  
 					IF state = Create THEN  
 						GetTempName( registerName, workName );  tempFile := TRUE
 						GetTempName( registerName, workName );  tempFile := TRUE
@@ -526,16 +531,26 @@ TYPE
 							RETURN;
 							RETURN;
 						END;
 						END;
 					END;
 					END;
-					r := Unix.unlink( ADDRESSOF( workName ) );
+					errno := Unix.unlink( ADDRESSOF( workName ) );
 					(*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
 					(*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
 					
 					
 					(*IF (FileTabSize - openfiles) < ResFiles THEN  Kernel.GC  END;*)
 					(*IF (FileTabSize - openfiles) < ResFiles THEN  Kernel.GC  END;*)
 						
 						
 					fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
 					fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
-					done := fd >= 0;  r := Unix.errno();
-					IF (~done & (r IN {Unix.ENFILE, Unix.EMFILE})) THEN
+					done := fd >= 0;  errno := Unix.errno();
+					IF (~done & (errno IN {Unix.ENFILE, Unix.EMFILE})) THEN
+						REPEAT
+							TRACE(errno, openfiles);
+							fo := openfiles;
+							Kernel.GC;
+							WaitClose(fo);
+							fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr);  errno := Unix.errno();
+						UNTIL (fd >= 0) OR ~ (errno IN  {Unix.ENFILE, Unix.EMFILE});
+						(*
+						TRACE(r, openfiles);
 						Kernel.GC; (*! + wait ? *)
 						Kernel.GC; (*! + wait ? *)
 						fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
 						fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
+						*)
 						done := fd >= 0
 						done := fd >= 0
 					END;
 					END;
 					IF done THEN
 					IF done THEN
@@ -543,11 +558,11 @@ TYPE
 							r := Unix.close( fd );  
 							r := Unix.close( fd );  
 							Halt( SELF, FALSE, "UnixFiles.File.Create: too many files open" )
 							Halt( SELF, FALSE, "UnixFiles.File.Create: too many files open" )
 						ELSE*)
 						ELSE*)
-							r := Unix.fstat( fd, stat );  
+							errno := Unix.fstat( fd, stat );  
 							dev := stat.dev;  ino := stat.ino;  mtime := stat.mtime.sec;
 							dev := stat.dev;  ino := stat.ino;  mtime := stat.mtime.sec;
 							state := Open;  fpos := 0;
 							state := Open;  fpos := 0;
 							(*fileTab[fd].f := SELF;*)
 							(*fileTab[fd].f := SELF;*)
-							INC( openfiles );  
+							IncOpenFiles();
 							
 							
 							collection.AddNew(SELF);
 							collection.AddNew(SELF);
 
 
@@ -813,7 +828,8 @@ TYPE
 							fd := NoDesc;
 							fd := NoDesc;
 						END;
 						END;
 					END;
 					END;
-					DEC( openfiles );  state := Closed;
+					DecOpenFiles();
+					state := Closed;
 				END Finalize;
 				END Finalize;
 				
 				
 				PROCEDURE Close;
 				PROCEDURE Close;
@@ -1150,6 +1166,23 @@ TYPE
 		collection.Finalize;
 		collection.Finalize;
 		unixFS.Finalize;
 		unixFS.Finalize;
 	END Finalization;
 	END Finalization;
+	
+	PROCEDURE DecOpenFiles;
+	BEGIN{EXCLUSIVE}
+		DEC(openfiles);
+	END DecOpenFiles;
+
+	PROCEDURE IncOpenFiles;
+	BEGIN{EXCLUSIVE}
+		INC(openfiles);
+	END IncOpenFiles;
+	
+	
+	PROCEDURE WaitClose(no: LONGINT);
+	BEGIN{EXCLUSIVE}
+		AWAIT(openfiles < no);
+	END WaitClose;
+	
 
 
 BEGIN
 BEGIN
 	Initialize;
 	Initialize;

+ 1 - 1
source/StdIOShell.Mod

@@ -45,7 +45,7 @@ SystemTools.DoCommands
 		Unix.StdIO.Mod Generic.Unix.Traps.Mod Locks.Mod Unix.Clock.Mod Disks.Mod Files.Mod Dates.Mod Strings.Mod 
 		Unix.StdIO.Mod Generic.Unix.Traps.Mod Locks.Mod Unix.Clock.Mod Disks.Mod Files.Mod Dates.Mod Strings.Mod 
 		UTF8Strings.Mod FileTrapWriter.Mod Caches.Mod DiskVolumes.Mod OldDiskVolumes.Mod RAMVolumes.Mod 
 		UTF8Strings.Mod FileTrapWriter.Mod Caches.Mod DiskVolumes.Mod OldDiskVolumes.Mod RAMVolumes.Mod 
 		DiskFS.Mod OldDiskFS.Mod OberonFS.Mod FATVolumes.Mod FATFiles.Mod ISO9660Volumes.Mod 
 		DiskFS.Mod OldDiskFS.Mod OberonFS.Mod FATVolumes.Mod FATFiles.Mod ISO9660Volumes.Mod 
-		ISO9660Files.Mod Generic.Unix.UnixFiles.Mod RelativeFileSystem.Mod BitSets.Mod StringPool.Mod DIagnostics.Mod 
+		ISO9660Files.Mod Generic.Unix.UnixFiles.Mod RelativeFileSystem.Mod BitSets.Mod StringPool.Mod Diagnostics.Mod 
 		ObjectFile.Mod GenericLinker.Mod GenericLoader.Mod Unix.BootConsole.Mod 
 		ObjectFile.Mod GenericLinker.Mod GenericLoader.Mod Unix.BootConsole.Mod 
 		Pipes.Mod Shell.Mod StdIOShell.Mod  
 		Pipes.Mod Shell.Mod StdIOShell.Mod