Parcourir la source

fixed a deadlock

git-svn-id: https://svn-dept.inf.ethz.ch/svn/lecturers/a2/trunk@8717 8c9fc860-2736-0410-a75d-ab315db34111
infsvn.guenter il y a 6 ans
Parent
commit
531fe28fd3
1 fichiers modifiés avec 39 ajouts et 17 suppressions
  1. 39 17
      source/Unix.TCP.Mod

+ 39 - 17
source/Unix.TCP.Mod

@@ -34,20 +34,44 @@ CONST
 VAR
 	trace: BOOLEAN;
 
+TYPE 
+	Sender = OBJECT
+		VAR 
+			conn: Connection;
+		
+			PROCEDURE &New( c: Connection );
+			BEGIN
+				conn := c
+			END New;
+			
+			PROCEDURE SendPacket( CONST data: ARRAY OF CHAR;  ofs, len: LONGINT ): BOOLEAN;
+			VAR n: LONGINT;
+			BEGIN {EXCLUSIVE}
+				WHILE len > 0 DO
+					n := len;
+					IF ~Sockets.Send( conn.socket, data, ofs, n ) THEN  RETURN FALSE  END;
+					DEC( len, n );  INC( ofs, n )						
+				END;
+				RETURN TRUE
+			END SendPacket;
+			
+	END Sender;
+	
+	
 TYPE
 	(** Connection object.
 		NOTE: Only one process should access a Connection!  *)
-
 	Connection* = OBJECT (Streams.Connection)
 			VAR
 				int-	: IP.Interface;	(*! Unix port: dummy, only 'int.localAdr' contains valid data *)
 				
 				lport-	: LONGINT;
-				fip-		: IP.Adr;  (* foreign protocol address *)
+				fip-	: IP.Adr;  (* foreign protocol address *)
 				fport-	: LONGINT;
 				state*	: SHORTINT;   (* TCP state *)
 
-				socket	: LONGINT;  localAdr, foreignAdr: Sockets.SocketAdr;
+				socket	: LONGINT;  
+				sender: Sender;
 				
 				(* the next variables are for interface compatibility only *)
 				irs-		: LONGINT;	(* initial receive sequence number *)
@@ -67,7 +91,8 @@ TYPE
 				(** Open a TCP connection (only use once per Connection instance).
 					Use TCP.NilPort for lport to automatically assign an unused local port.*)
 				PROCEDURE Open*( lport: LONGINT;  fip: IP.Adr;  fport: LONGINT;  VAR res: WORD );
-				VAR ignore: BOOLEAN;
+				VAR
+					localAdr, foreignAdr: Sockets.SocketAdr;
 				BEGIN {EXCLUSIVE}
 					ASSERT( (state = Unused) & (lport >= 0) & (lport < 10000H) & (fport >= 0) & (fport < 10000H) );
 					IF trace THEN  Out.String( "Open connection " )  END;
@@ -78,11 +103,13 @@ TYPE
 							(* active open (connect) *)
 							foreignAdr := Sockets.NewSocketAdr( fip, fport );
 							IF Sockets.Connect( socket, foreignAdr ) THEN
-								ignore := Sockets.SetLinger( socket );
+								IGNORE Sockets.SetLinger( socket );
 								SELF.fip := fip;  SELF.fport := fport;
 								localAdr := Sockets.GetSockName( socket );
 								SELF.lport := Sockets.GetPortNumber( localAdr );
-								state := Established;  res := Ok
+								state := Established;  
+								NEW( sender, SELF );
+								res := Ok
 							ELSE  
 								Out.String( "connect failed" ); Out.Ln;
 								Sockets.Close( socket );  res := ConnectionRefused
@@ -96,7 +123,7 @@ TYPE
 								localAdr := Sockets.GetSockName( socket );
 								SELF.lport := Sockets.GetPortNumber( localAdr );
 								IF Sockets.Listen( socket ) THEN
-									ignore := Sockets.SetLinger( socket );
+									IGNORE Sockets.SetLinger( socket );
 									SELF.fip := IP.NilAdr;
 									state := Listen;  res := Ok
 								ELSE  Sockets.Close( socket );  res := NotConnected
@@ -127,18 +154,13 @@ TYPE
 
 				(** Send data on a TCP connection. *)
 				PROCEDURE Send*( CONST data: ARRAY OF CHAR;  ofs, len: LONGINT;  propagate: BOOLEAN;  VAR res: WORD );
-				VAR n: LONGINT;
-				BEGIN {EXCLUSIVE}
+				BEGIN 
 					IF trace THEN  Out.String( "Send: socket=" );  Out.Int( socket, 0 )  END;
 					IF state = Established THEN
-						res := Ok;
-						WHILE len > 0 DO
-							n := len;
-							IF Sockets.Send( socket, data, ofs, n ) THEN  
-								DEC( len, n );  INC( ofs, n )
-							ELSE  
-								res := ConnectionReset;  len := 0
-							END
+						IF sender.SendPacket( data, ofs, len ) THEN  
+							res := Ok
+						ELSE  
+							res := ConnectionReset
 						END
 					ELSE
 						res := NotConnected (* Send on a Connection with state=Listen *)