You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

释放Indy SSLIOHandler时触发访问违规的问题求助

解决单例TRestClient释放时ssl_shutdown访问违规问题

问题根源

单例实例的释放时机通常在程序退出阶段,此时Indy依赖的OpenSSL库可能已被系统或其他组件提前卸载,或是全局SSL上下文已销毁,导致调用ssl_shutdown时访问无效内存。而瞬态实例在程序运行期间释放,此时SSL库仍处于正常加载状态,因此无异常。

具体解决思路

  • 提前手动触发资源清理
    不要依赖程序退出时的自动析构,在主窗体关闭前(如FormCloseQuery事件),主动获取Spring4D管理的单例实例,调用自定义清理方法提前释放TRestClient资源,避免析构阶段的时序问题。示例代码:

    procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    var
      BaseSvc: IBaseService;
    begin
      BaseSvc := ServiceLocator.GetService<IBaseService>;
      (BaseSvc as TBaseService).CleanupRestClient;
    end;
    
    // 在TBaseService中实现清理方法
    procedure TBaseService.CleanupRestClient;
    begin
      if Assigned(FRestClient) then
      begin
        // 若能获取内部TIdHTTP实例,先主动断开连接
        (FRestClient as IRESTClientAccess).GetIdHTTP.Disconnect;
        FreeAndNil(FRestClient);
      end;
    end;
    
  • 拆分SSLIOHandler生命周期管理
    让BaseService直接持有SSLIOHandler的引用,释放TRestClient前先手动断开SSL连接并释放SSLIOHandler,避免TRestClient析构时触发无效的SSL操作:

    1. 在TBaseService中添加成员FSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
    2. 创建TRestClient时,将FSSLHandler传入并保留引用
    3. 清理时先执行FSSLHandler.Close; FreeAndNil(FSSLHandler);,再释放TRestClient
  • 禁用自动SSL Shutdown
    创建TIdSSLIOHandlerSocketOpenSSL时,手动关闭自动断开时的SSL清理逻辑,避免析构阶段调用无效的ssl_shutdown:

    FSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    FSSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];
    FSSLHandler.OnDisconnect := nil; // 禁用自动断开时的SSL处理
    
  • 调整单例释放优先级
    在Spring4D容器配置单例时,设置更高的释放优先级,确保BaseService在OpenSSL库卸载前完成资源释放:

    GlobalContainer.RegisterType<TBaseService>.AsSingleton.WithReleasePriority(1);
    

    (数值越小优先级越高,会更早被容器释放)

额外注意事项

  • 不要手动调用FreeLibrary卸载OpenSSL库,交由系统自动处理卸载时机
  • 确保所有REST请求完成后再执行释放操作,避免在存在未完成SSL连接时清理资源

内容的提问来源于stack exchange,提问作者jdetaeye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:07:17