11-- ----------------------------------------------------------------------------
22-- Ada Web Server --
33-- --
4- -- Copyright (C) 2012-2019 , AdaCore --
4+ -- Copyright (C) 2012-2021 , AdaCore --
55-- --
66-- This library is free software; you can redistribute it and/or modify --
77-- it under terms of the GNU General Public License as published by the --
@@ -161,10 +161,14 @@ package body AWS.Net.WebSocket.Registry is
161161 entry Get_Socket (WebSocket : out Object_Class);
162162 -- Get a WebSocket having some data to be sent
163163
164- procedure Release_Socket (WebSocket : Object_Class);
164+ procedure Release_Socket (WebSocket : in out Object_Class);
165165 -- Release a socket retrieved with Get_Socket above, this socket will be
166166 -- then available again.
167167
168+ procedure Free (WebSocket : in out Object_Class);
169+ -- Free WebSocket immediately if not taken by another task, otherwise
170+ -- record it to be freed as soon as it is released.
171+
168172 entry Not_Empty;
169173 -- Returns if the Set is not empty
170174
@@ -329,7 +333,7 @@ package body AWS.Net.WebSocket.Registry is
329333
330334 procedure Do_Free (WebSocket : in out Object_Class) is
331335 begin
332- Unchecked_Free (WebSocket);
336+ DB.Free (WebSocket);
333337 end Do_Free ;
334338
335339 -- ---------------
@@ -442,7 +446,7 @@ package body AWS.Net.WebSocket.Registry is
442446 end ;
443447
444448 WebSocket.Shutdown;
445- Unchecked_Free (WebSocket);
449+ DB.Free (WebSocket);
446450 end if ;
447451 end Close_To ;
448452
@@ -499,7 +503,7 @@ package body AWS.Net.WebSocket.Registry is
499503 Socket.On_Close (Message);
500504 Socket.Shutdown;
501505
502- Unchecked_Free (W);
506+ DB.Free (W);
503507 end Close ;
504508
505509 -- --------------
@@ -516,9 +520,11 @@ package body AWS.Net.WebSocket.Registry is
516520 -- Add watched sockets
517521
518522 for Id of Watched loop
519- FD_Set.Add
520- (Result,
521- Registered (Id).all , Registered (Id), FD_Set.Input);
523+ if not Registered (Id).To_Free then
524+ FD_Set.Add
525+ (Result,
526+ Registered (Id).all , Registered (Id), FD_Set.Input);
527+ end if ;
522528 end loop ;
523529 end return ;
524530 end Create_Set ;
@@ -555,7 +561,7 @@ package body AWS.Net.WebSocket.Registry is
555561 end ;
556562
557563 WebSocket.Shutdown;
558- Unchecked_Free (WebSocket);
564+ DB.Free (WebSocket);
559565 end On_Close ;
560566
561567 begin
@@ -568,6 +574,24 @@ package body AWS.Net.WebSocket.Registry is
568574 Registered.Clear;
569575 end Finalize ;
570576
577+ -- --------
578+ -- Free --
579+ -- --------
580+
581+ procedure Free (WebSocket : in out Object_Class) is
582+ begin
583+ -- If WebSocket is in Sending it means that it has been
584+ -- taken by the Get_Socket call. We cannot free it now, we
585+ -- record this socket to be freed as soon as it is released
586+ -- (Release_Socket) call.
587+
588+ if Sending.Contains (WebSocket.Id) then
589+ WebSocket.To_Free := True;
590+ else
591+ Unchecked_Free (WebSocket);
592+ end if ;
593+ end Free ;
594+
571595 -- --------------
572596 -- Get_Socket --
573597 -- --------------
@@ -738,10 +762,19 @@ package body AWS.Net.WebSocket.Registry is
738762 -- Release_Socket --
739763 -- ------------------
740764
741- procedure Release_Socket (WebSocket : Object_Class) is
765+ procedure Release_Socket (WebSocket : in out Object_Class) is
742766 begin
743767 Sending.Exclude (WebSocket.Id);
744- New_Pending := True;
768+
769+ -- The socket has been recorded to be freed. It is not anymore
770+ -- in the registry, we just need to free it now that it has
771+ -- been released.
772+
773+ if WebSocket.To_Free then
774+ Unchecked_Free (WebSocket);
775+ else
776+ New_Pending := True;
777+ end if ;
745778 end Release_Socket ;
746779
747780 -- ----------
@@ -869,15 +902,15 @@ package body AWS.Net.WebSocket.Registry is
869902 begin
870903 if Error = null then
871904 DB.Unregister (W);
872- Unchecked_Free (W);
905+ DB.Free (W);
873906
874907 else
875908 Error (W.all , A);
876909
877910 case A is
878911 when Close =>
879912 DB.Unregister (W);
880- Unchecked_Free (W);
913+ DB.Free (W);
881914 when None =>
882915 null ;
883916 end case ;
@@ -931,9 +964,7 @@ package body AWS.Net.WebSocket.Registry is
931964 WS.Close (Exception_Message (E), Going_Away);
932965 WS.On_Close (Exception_Message (E));
933966
934- -- ??? if we free it now, there might be a reader
935- -- in parallel that is using this socket...
936- Unchecked_Free (WS);
967+ DB.Free (WS);
937968
938969 -- No more data to send from this socket
939970 Pending := 0 ;
@@ -996,7 +1027,7 @@ package body AWS.Net.WebSocket.Registry is
9961027 WebSocket.Close (Exception_Message (E), Going_Away);
9971028
9981029 -- Do not free, it might be used by another
999- Unchecked_Free (WebSocket);
1030+ Free (WebSocket);
10001031 end ;
10011032
10021033 else
@@ -1267,7 +1298,7 @@ package body AWS.Net.WebSocket.Registry is
12671298 DB.Unregister (WS);
12681299 WebSocket_Exception
12691300 (WS, Exception_Message (E), Protocol_Error);
1270- Unchecked_Free (WS);
1301+ DB.Free (WS);
12711302 -- No more data to send from this socket
12721303 Pending := 0 ;
12731304 end Read_Send ;
@@ -1539,7 +1570,7 @@ package body AWS.Net.WebSocket.Registry is
15391570 DB.Watch (WebSocket);
15401571 exception
15411572 when others =>
1542- Unchecked_Free (WebSocket);
1573+ DB.Free (WebSocket);
15431574 raise ;
15441575 end Watch ;
15451576
0 commit comments