[vlc-devel] [PATCH] Support for alternative libv4l2 library (userspace drivers)
Rémi Denis-Courmont
remi at remlab.net
Fri Aug 1 18:32:39 CEST 2014
Le 2014-08-01 19:07, Markus Rechberger a écrit :
> libv4l2 accesses device nodes, our one communicates via unix domain
> sockets to a local server the v4l2 API is fully compatible but the
> interface is different of course. I just mean that the API calls are
> fully compatible. The underlying architecture is completely
> different.
As far as I understand, v4l2_fd_open() does not really care what type
of file descriptor you feed it. As long as the file path can be opened
in read/write mode, it should work just fine. Of course a socket cannot
be opened, at least not with open/openat, but that is an internal
implementation issue. You can still get the application to pass a
regular file or a named pipe descriptor to v4l2_fd_open() and then
switch to a socket in the V4L plugin initialization.
>> + int fd;
>> + char *buf=NULL;
>> + int buflen=0;
>> + int nread;
>> + char rbuf[10240];
>> + int rv;
>> + struct stat statbuf;
>> +
>> + const char *sockpath="@/de/sundtek/mediasocket";
>> +
>> + /* FreeBSD, Solaris, MacOSX */
>> + rv = stat("/tmp/.mediasocket", &statbuf);
>> + if (rv == 0)
>> + return 0;
>>
>> Looks very much like a TOCTOU race.
>>
>> Ditto for the procfs check.
>>
>> +
>> + fd = open("/proc/net/unix", O_RDONLY);
>>
>> Missing close-on-exec.
>>
>
> close-on-exec is handled in the library already.
Uh? open() does not set close-on-exec by default, and it would be a
serious problem if the run-time did it, since it would break those
programs that do need to preserve file descriptors across exec().
>> + free(buf);
>> + close(fd);
>> + return 0;
>> + }
>> + close(fd);
>> + free(buf);
>> + }
>> + return -1;
>> +}
>> +
>> +static int v4l2_net_open (char *path) {
>> + void *h;
>> + int fd;
>> +
>> + h = dlopen ("libmcsimple.so", RTLD_LAZY | RTLD_LOCAL);
>> + if (h == NULL) {
>> + /* this is the default driver location */
>> + h = dlopen("/opt/lib/libmcsimple.so", RTLD_LAZY |
>> RTLD_LOCAL);
>>
>> From a quick glance, that library is not reentrant.
>>
>
> the library has locking inside to avoid race conditions.
I have to doubt that. For one thing, a quick objdump shows strerror()
calls and strerror() is not reentrant at least not on GNU/Linux.
>> + if (h == NULL)
>> + goto fallback;
>> + }
>> + /* no need for that one */
>> + v4l2_open_direct = dlsym (h, "net_open");
>> + v4l2_close = dlsym (h, "net_close");
>> + v4l2_ioctl = dlsym (h, "net_ioctl");
>> + v4l2_read = dlsym (h, "__net_read");
>> + v4l2_mmap = dlsym (h, "net_mmap");
>> + v4l2_munmap = dlsym (h, "net_munmap");
>>
>> This breaks reentrancy and the memory model.
>> The reast of the assumes that the back-end library is constant
>> throughout
>> the lifetime of the process.
>>
>
> I see what you mean here, I'll do some further tests.
> But I guess it should be more dynamic and just be checked when the
> user tries to open a node.
In general, we do not support updating VLC underlying libraries live;
we just keep the old library version in memory. I cannot conceive any
other corner case.
Unloading and reloading the library everytime would be a waste, not to
mention the increased risk of memory leaks (should the library have any
static data).
> Aside of that I was wondering about the pthread_once inside the
> original source, can you elaborate what the purpose
> of that is instead of doing those things directly without
> pthread_once?
Reentrancy is the whole point. While unlikely, nothing (else) truly
prevents two concurrent calls.
--
Rémi Denis-Courmont
More information about the vlc-devel
mailing list