Web lists-archives.com

[Spca50x-devs] uvc open/close race (Was Re: v4l1 compat wrapper version 0.3)




Laurent Pinchart wrote:
Hi Hans,

On Friday 06 June 2008 15:00, Hans de Goede wrote:
Hi All,

Ok, this one _really_ works with ekiga (and still works fine with spcaview)
and also works with camorama with selected cams (not working on some cams
due to a camorama bug).

Changes:
* Don't allow multiple opens, in theory our code can handle it, but not all
   v4l2 devices like it (ekiga does it and uvc doesn't like it).

Could you please elaborate ? Have you noticed a bug in the UVC driver ? It should support multiple opens.

A good question, which I kinda knew I had coming. So now it has been asked I've spend some time tracking this down. There seems to be an open/close race somewhere in the UVC driver, ekiga does many open/close cycles in quick succession during probing.

It seems my no multiple opens code slows it down just enough to stop the race, but indeed multiple opens does not seem to be the real problem.

I've attached a program which reproduces it. I've commented out the fork as that does not seem necessary to reproduce this, just very quickly doing open/some-io/close, open/some-io/close seems to be enough to trigger this, here is the output on my machine:

[hans@localhost v4l1-compat-0.4]$ ./test
[hans@localhost v4l1-compat-0.4]$ ./test
[hans@localhost v4l1-compat-0.4]$ ./test
[hans@localhost v4l1-compat-0.4]$ ./test
TRY_FMT 2: Input/output error
[hans@localhost v4l1-compat-0.4]$ ./test
TRY_FMT 1: Input/output error
[hans@localhost v4l1-compat-0.4]$ ./test
TRY_FMT 1: Input/output error
[hans@localhost v4l1-compat-0.4]$ ./test
TRY_FMT 1: Input/output error
[hans@localhost v4l1-compat-0.4]$

Notice how after the first time it gets the I/O error, it never recovers and from now on every first TRY_FMT fails.

Some notes:
1) TRY_FMT should really never do I/O (but then I guess the
   problem would still persists with S_FMT)
2) I've also seen it fail at TRY_FMT 1 without first failing
   a TRY_FMT 2, I guess that was just me doing arrow-up -> enter to quickly :)

Regards,

Hans
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <syscall.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>

int main(void)
{
  int fd;
  pid_t pid;
  struct v4l2_format fmt2 = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
  
  fd = open("/dev/video0", O_RDONLY);
  if (fd == -1) {
    perror("open 1");
    return 1;
  }

  if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt2)) {
    perror("G_FMT 1");
    return 1;
  }
      
  if (syscall(SYS_ioctl, fd, VIDIOC_TRY_FMT, &fmt2)) {
    perror("TRY_FMT 1");
    return 1;
  }

  if (syscall(SYS_ioctl, fd, VIDIOC_S_FMT, &fmt2)) {
    perror("S_FMT 1");
    return 1;
  }

/*  pid = fork();
  if (pid == -1) {
    perror("fork");
    return 1;
  }
  
  if (!pid) {
    close(fd);
  } else */ {
    close(fd);
    fd = open("/dev/video0", O_RDONLY);
    if (fd == -1) {
      perror("open 2");
      return 1;
    }

    if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt2)) {
      perror("G_FMT 2");
      return 1;
    }
        
    if (syscall(SYS_ioctl, fd, VIDIOC_TRY_FMT, &fmt2)) {
      perror("TRY_FMT 2");
      return 1;
    }

    if (syscall(SYS_ioctl, fd, VIDIOC_S_FMT, &fmt2)) {
      perror("S_FMT 2");
      return 1;
    }
  }
  return 0;
}
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Spca50x-devs mailing list
Spca50x-devs@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/spca50x-devs