ais_v4l2_proxy dma fd 泄露问题调查

静态代码排查

1、v4l2 hal 绑定dma fd

在这里插入图片描述
如上时序图:
在app open camera 的时候,就会调用到camera的openCamera(),最后会调用到v4l2_wrapper的CreateInputSurface(), 在这个方法里面会根据当前为这个camera 分配对应的MAX_BUFFER_NUM

int V4L2Wrapper::Init() {
  ......
  // Format changed, request new buffers.
  if (isSRVMCamera()) {
      res = RequestBuffers(MAX_SRVM_BUFFER_NUM);
  }else {
      res = RequestBuffers(MAX_BUFFER_NUM);
  }
  ......
}
int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
  ......
  int result =  CreateInputSurfaces(num_requested);
  ......
}
int32_t V4L2Wrapper::CreateInputSurface(int32_t index) {
    .......
    v4l2_buffer device_buffer;
    memset(&device_buffer, 0, sizeof(device_buffer));
    device_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    device_buffer.memory = V4L2_MEMORY_MMAP;
    device_buffer.index = index;

    // Use QUERYBUF to ensure our buffer/device is in good shape,
    // and fill out remaining fields.
    if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
        HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
        return -ENODEV;
    }

    if (input_buffer_infos[index].isUsed) {
      HAL_LOGE("ERROR: index:%d, isUsed:%d", index,
          input_buffer_infos[index].isUsed);
        
      // 这个input_buffer_infos后面会做c2d的时候用  
      input_buffer_infos[index].gpuAddr = NULL;
      input_buffer_infos[index].virtPtr = NULL;
      input_buffer_infos[index].surfaceId = 0;
      input_buffer_infos[index].isUsed = false;
      input_buffer_infos[index].id = 0;

      if (input_buffer_infos[index].fd >= 0) {
        close(input_buffer_infos[index].fd);
      }

      memset(&input_buffer_infos[index], 0, sizeof(buffer_info_t));
    }

    struct v4l2_exportbuffer expbuf = { 0 };
    expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    expbuf.index = index;
    expbuf.plane = 1;
    expbuf.flags = O_CLOEXEC | O_RDWR;

    // 这里就会调用到v4l2loopback里面,然后就会调用到ais_v4l2_proxy的processAllocBufs里面将最终用做数据传输的buffer fd返回给
    input_buffer_infos
    if (IoctlLocked(VIDIOC_EXPBUF, &expbuf) < 0)
    {
        HAL_LOGE("EXPBUF failed err= %s index %x", strerror(-errno), index);
        return 1;
    }

    input_buffer_infos[index].width = mInputWidth;
    input_buffer_infos[index].height = mInputHeight;
    input_buffer_infos[index].cropWidth = mInputCropWidth;
    input_buffer_infos[index].cropHeight = mInputCropHeight;
    input_buffer_infos[index].cropLeft = mInputCropLeft;
    input_buffer_infos[index].cropTop = mInputCropTop;
    input_buffer_infos[index].halFormat = mInputHalFormat;
    // 这里fd, 会关联到dma buffer -> GraphicBuffer -> window -> fd
    input_buffer_infos[index].fd = expbuf.fd; //dup(device_fd_.get());
    input_buffer_infos[index].length = device_buffer.length;
    input_buffer_infos[index].offset = device_buffer.m.offset;
    input_buffer_infos[index].id = index;
    ........
}

在这里插入图片描述

2、v4l2 hal 销毁dma fd

在这里插入图片描述
以上是销毁dma buffer 的流程,在调用close camera的时候就会去销毁dma buffer既销毁dma fd。

分析历程一:

在帧率正常的情况下,去切换流媒体(open)和sideview(close), 都会看到dma fd的减少和增加, 符合预期和流程
在帧率异常的情况下,sideview 在不断的被打开成功,但是没有帧率过来。随后buffer等待超时,返回camera failed给app, app 下发close 关闭 camera,按理说也会随着close camera ,去销毁dma fd,但是从检测的报告来看dma fd好像没有随着close camera减少,open camera的时候还增加了。
两者差异就在这个等待的buffer,但是代码静态分析,等待的请求buffer在close camera的时候也会随着清除掉。

分析历程二

发现只要是帧率异常,有超时上报就会有dma fd堆积,rvc camera也会出现此问题,通过lsof 查看该fd的占用情况,只有ais_v4l2_proxy 占用
在这里插入图片描述
在创建和销毁fd的地方都加上了log
在这里插入图片描述
在这里插入图片描述
最后发现这些未销毁的fd值,不在上面创建和销毁的log里面

分析历程三

在帧率正常的情况下,来回切换流媒体/sideview 发现dmabuf fd也会增加,那就推反了上面分析一、二,怀疑点就在open/close的情况会增加了,和生产者buffer堆积没有关系了。
再继续做静态代码分析,发现如下
在这里插入图片描述
Dmabuf fd间接来自GraphicBuffer转换而来,但是在销毁的时候虽然close了fd,但是只对calloc的地址进行了free,而没有对里面的对象清除
在这里插入图片描述
在这里插入图片描述
再销毁具体的GraphicBuffer对象后,发现dmabuf就没有再增加了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值