shutdown fixes, error event handling
This commit is contained in:
parent
491206d8fb
commit
b85079a7cb
|
@ -184,6 +184,9 @@ uses
|
|||
IdCoderMIME, SysUtils, Math, IdException, IdStackConsts, IdStack,
|
||||
IdStackBSDBase, IdGlobal, Windows, StrUtils, DateUtils;
|
||||
|
||||
var
|
||||
GUnitFinalized: Boolean = false;
|
||||
|
||||
//type
|
||||
// TAnonymousThread = class(TThread)
|
||||
// protected
|
||||
|
@ -1148,6 +1151,8 @@ procedure TIdWebsocketMultiReadThread.AddClient(
|
|||
var l: TList;
|
||||
begin
|
||||
//Assert( (aChannel.IOHandler as TIdIOHandlerWebsocket).IsWebsocket, 'Channel is not a websocket');
|
||||
if Self = nil then Exit;
|
||||
if Self.Terminated then Exit;
|
||||
|
||||
l := FChannels.LockList;
|
||||
try
|
||||
|
@ -1212,6 +1217,13 @@ end;
|
|||
|
||||
destructor TIdWebsocketMultiReadThread.Destroy;
|
||||
begin
|
||||
if FReconnectThread <> nil then
|
||||
begin
|
||||
FReconnectThread.Terminate;
|
||||
FReconnectThread.WaitFor;
|
||||
FReconnectThread.Free;
|
||||
end;
|
||||
|
||||
IdWinsock2.closesocket(FTempHandle);
|
||||
FTempHandle := 0;
|
||||
FChannels.Free;
|
||||
|
@ -1256,6 +1268,8 @@ class function TIdWebsocketMultiReadThread.Instance: TIdWebsocketMultiReadThread
|
|||
begin
|
||||
if (FInstance = nil) then
|
||||
begin
|
||||
if GUnitFinalized then Exit(nil);
|
||||
|
||||
FInstance := TIdWebsocketMultiReadThread.Create(True);
|
||||
FInstance.Start;
|
||||
end;
|
||||
|
@ -1269,6 +1283,8 @@ var
|
|||
ws: TIdIOHandlerWebsocket;
|
||||
i: Integer;
|
||||
begin
|
||||
if Terminated then Exit;
|
||||
|
||||
l := FChannels.LockList;
|
||||
try
|
||||
for i := 0 to l.Count - 1 do
|
||||
|
@ -1311,8 +1327,11 @@ begin
|
|||
FChannels.UnlockList;
|
||||
end;
|
||||
|
||||
if Terminated then Exit;
|
||||
|
||||
//reconnect needed? (in background)
|
||||
if (FReconnectlist <> nil) and (FReconnectlist.Count > 0) then
|
||||
if FReconnectlist <> nil then
|
||||
if FReconnectlist.Count > 0 then
|
||||
begin
|
||||
if FReconnectThread = nil then
|
||||
FReconnectThread := TIdWebsocketQueueThread.Create(False{direct start});
|
||||
|
@ -1456,7 +1475,8 @@ begin
|
|||
//some data?
|
||||
if (iResult > 0) then
|
||||
begin
|
||||
//strmEvent := nil;
|
||||
//make sure the thread is created outside a lock
|
||||
TIdWebsocketDispatchThread.Instance;
|
||||
|
||||
l := FChannels.LockList;
|
||||
if l = nil then Exit;
|
||||
|
@ -1503,6 +1523,7 @@ procedure TIdWebsocketMultiReadThread.RemoveClient(
|
|||
aChannel: TIdHTTPWebsocketClient);
|
||||
begin
|
||||
if Self = nil then Exit;
|
||||
if Self.Terminated then Exit;
|
||||
|
||||
aChannel.Lock;
|
||||
try
|
||||
|
@ -1516,18 +1537,23 @@ begin
|
|||
end;
|
||||
|
||||
class procedure TIdWebsocketMultiReadThread.RemoveInstance(aForced: boolean);
|
||||
var
|
||||
o: TIdWebsocketMultiReadThread;
|
||||
begin
|
||||
if FInstance <> nil then
|
||||
begin
|
||||
FInstance.Terminate;
|
||||
o := FInstance;
|
||||
FInstance := nil;
|
||||
|
||||
if aForced then
|
||||
begin
|
||||
WaitForSingleObject(FInstance.Handle, 2 * 1000);
|
||||
TerminateThread(FInstance.Handle, MaxInt);
|
||||
WaitForSingleObject(o.Handle, 2 * 1000);
|
||||
TerminateThread(o.Handle, MaxInt);
|
||||
end
|
||||
else
|
||||
FInstance.WaitFor;
|
||||
FreeAndNil(FInstance);
|
||||
o.WaitFor;
|
||||
FreeAndNil(o);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -1544,6 +1570,8 @@ end;
|
|||
procedure TIdWebsocketMultiReadThread.Terminate;
|
||||
begin
|
||||
inherited Terminate;
|
||||
if FReconnectThread <> nil then
|
||||
FReconnectThread.Terminate;
|
||||
|
||||
FChannels.LockList;
|
||||
try
|
||||
|
@ -1560,6 +1588,8 @@ class function TIdWebsocketDispatchThread.Instance: TIdWebsocketDispatchThread;
|
|||
begin
|
||||
if FInstance = nil then
|
||||
begin
|
||||
if GUnitFinalized then Exit(nil);
|
||||
|
||||
GlobalNameSpace.BeginWrite;
|
||||
try
|
||||
if FInstance = nil then
|
||||
|
@ -1575,17 +1605,22 @@ begin
|
|||
end;
|
||||
|
||||
class procedure TIdWebsocketDispatchThread.RemoveInstance;
|
||||
var
|
||||
o: TIdWebsocketDispatchThread;
|
||||
begin
|
||||
if FInstance <> nil then
|
||||
begin
|
||||
FInstance.Terminate;
|
||||
o := FInstance;
|
||||
FInstance := nil;
|
||||
|
||||
if aForced then
|
||||
begin
|
||||
WaitForSingleObject(FInstance.Handle, 2 * 1000);
|
||||
TerminateThread(FInstance.Handle, MaxInt);
|
||||
WaitForSingleObject(o.Handle, 2 * 1000);
|
||||
TerminateThread(o.Handle, MaxInt);
|
||||
end;
|
||||
FInstance.WaitFor;
|
||||
FreeAndNil(FInstance);
|
||||
o.WaitFor;
|
||||
FreeAndNil(o);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -1604,7 +1639,9 @@ end;
|
|||
|
||||
initialization
|
||||
finalization
|
||||
GUnitFinalized := True;
|
||||
if TIdWebsocketMultiReadThread.Instance <> nil then
|
||||
TIdWebsocketMultiReadThread.Instance.Terminate;
|
||||
TIdWebsocketDispatchThread.RemoveInstance();
|
||||
TIdWebsocketMultiReadThread.RemoveInstance();
|
||||
TIdWebsocketDispatchThread.RemoveInstance()
|
||||
|
||||
end.
|
||||
|
|
|
@ -6,7 +6,7 @@ uses
|
|||
Classes, Generics.Collections,
|
||||
superobject,
|
||||
IdServerBaseHandling, IdContext, IdException, IdIOHandlerWebsocket, IdHTTP,
|
||||
SyncObjs;
|
||||
SyncObjs, SysUtils;
|
||||
|
||||
type
|
||||
TSocketIOContext = class;
|
||||
|
@ -22,6 +22,7 @@ type
|
|||
TSocketIONotify = reference to procedure(const ASocket: ISocketIOContext);
|
||||
TSocketIOEvent = reference to procedure(const ASocket: ISocketIOContext; const aArgument: TSuperArray; const aCallback: ISocketIOCallback);
|
||||
TSocketIOError = reference to procedure(const ASocket: ISocketIOContext; const aErrorClass, aErrorMessage: string);
|
||||
TSocketIOEventError = reference to procedure(const ASocket: ISocketIOContext; const aCallback: ISocketIOCallback; E: Exception);
|
||||
|
||||
TSocketIONotifyList = class(TList<TSocketIONotify>);
|
||||
TSocketIOEventList = class(TList<TSocketIOEvent>);
|
||||
|
@ -139,6 +140,8 @@ type
|
|||
FOnSocketIOJson: TSocketIOMsgJSON;
|
||||
|
||||
procedure ProcessEvent(const AContext: TSocketIOContext; const aText: string; aMsgNr: Integer; aHasCallback: Boolean);
|
||||
private
|
||||
FOnEventError: TSocketIOEventError;
|
||||
protected
|
||||
type
|
||||
TSocketIOCallback = procedure(const aData: string) of object;
|
||||
|
@ -194,6 +197,7 @@ type
|
|||
procedure OnEvent (const aEventName: string; const aCallback: TSocketIOEvent);
|
||||
procedure OnConnection(const aCallback: TSocketIONotify);
|
||||
procedure OnDisconnect(const aCallback: TSocketIONotify);
|
||||
property OnEventError: TSocketIOEventError read FOnEventError write FOnEventError;
|
||||
|
||||
procedure EnumerateSockets(const aEachSocketCallback: TSocketIONotify);
|
||||
end;
|
||||
|
@ -208,7 +212,7 @@ type
|
|||
implementation
|
||||
|
||||
uses
|
||||
SysUtils, StrUtils, IdServerWebsocketContext, IdHTTPWebsocketClient, Windows;
|
||||
StrUtils, IdServerWebsocketContext, IdHTTPWebsocketClient, Windows;
|
||||
|
||||
procedure TIdBaseSocketIOHandling.AfterConstruction;
|
||||
begin
|
||||
|
@ -500,16 +504,16 @@ begin
|
|||
callback := TSocketIOCallbackObj.Create(Self, AContext, aMsgNr)
|
||||
else
|
||||
callback := nil;
|
||||
try
|
||||
try
|
||||
for event in list do
|
||||
try
|
||||
event(AContext, args, callback);
|
||||
except
|
||||
on E:Exception do
|
||||
begin
|
||||
except on E:Exception do
|
||||
if Assigned(OnEventError) then
|
||||
OnEventError(AContext, callback, e)
|
||||
else
|
||||
if callback <> nil then
|
||||
callback.SendResponse( SO(['Error', e.Message]).AsJSon );
|
||||
end;
|
||||
callback.SendResponse( SO(['Error', SO(['msg', e.message])]).AsJSon );
|
||||
end;
|
||||
finally
|
||||
callback := nil;
|
||||
|
|
|
@ -116,18 +116,21 @@ procedure TROIndyHTTPWebsocketChannel.SetHost(const Value: string);
|
|||
begin
|
||||
IndyClient.Host := Value;
|
||||
TargetURL := Format('ws://%s:%d/%s', [Host, Port, WSResourceName]);
|
||||
FTriedUpgrade := False; //reset
|
||||
end;
|
||||
|
||||
procedure TROIndyHTTPWebsocketChannel.SetPort(const Value: integer);
|
||||
begin
|
||||
IndyClient.Port := Value;
|
||||
TargetURL := Format('ws://%s:%d/%s', [Host, Port, WSResourceName]);
|
||||
FTriedUpgrade := False; //reset
|
||||
end;
|
||||
|
||||
procedure TROIndyHTTPWebsocketChannel.SetWSResourceName(const Value: string);
|
||||
begin
|
||||
IndyClient.WSResourceName := Value;
|
||||
TargetURL := Format('ws://%s:%d/%s', [Host, Port, WSResourceName]);
|
||||
FTriedUpgrade := False; //reset
|
||||
end;
|
||||
|
||||
function TROIndyHTTPWebsocketChannel.GetHost: string;
|
||||
|
|
Loading…
Reference in a new issue