Scaling the time

lun. 24 septembre 2012 by Rémi Duraffort

Using valgrind on time-dependent softwares like VLC media player is often a nightmare and leads to poor results. Let's present a simple and elegant way to workaround this issue

Valgrind and realtime softwares

Valgrind is a really useful tool that checks for memory leaks, wrong memory access and many more properties. In order to achieve this task, valgrind will scrutinize every instructions that manipulate memory executed by the tested program. This process will slow down the application by a factor from 5 to 100 times.

Most of the time, this slowdown will not change the final behavior and results.

However some applications, like VLC media player, use time dependent algorithms that will be affected by such slow down. For instance, if you run VLC under valgrind while decoding an HD video:

$ valgrind --leak-check=full ./vlc -I dummy -A dummy video.mkv
[...]
VLC media player 2.1.0-git Rincewind (revision 1.3.0-git-3513-g970b2ac)
[0x7115ef8] dummy interface: using the dummy interface module...
[0x7883748] avcodec decoder error: more than 5 seconds of late video -> dropping frame (computer too slow ?)
[0x7883748] avcodec decoder error: more than 5 seconds of late video -> dropping frame (computer too slow ?)
[0x7883748] avcodec decoder error: more than 5 seconds of late video -> dropping frame (computer too slow ?)
[0x7883748] avcodec decoder error: more than 5 seconds of late video -> dropping frame (computer too slow ?)

VLC is printing errors and not displaying the video because of the slow down. The behavior of VLC is highly affected as most pictures will not be decoded in time and will be dropped without being displayed.

Hiding bugs from valgrind

Most people will think that this is not an issue as we only use valgrind for debugging and that we expect the video player not to be usable in this case. In fact, this will change the behavior of VLC and may mask out some bugs in the application.

VLC will not follows the normal path and will take shortcuts to drop the video. If a bug is hidden in the last stage of the decoding pipeline, we won't be able to see it under valgrind monitoring.

Let's look at this simple source code that leaks under normal circumstances but not when ran under valgrind:

#include <stdio.h>
#include <math.h>
#include <time.h>
int main()
{
    int i;
    double j = 0.0;
    time_t begin = time(NULL);
    for(i = 0; i < 100000000; i++)
        j += sqrt(i);
    time_t end = time(NULL);
    /* We cannot wait for more than 5 seconds for this computation */
    if(end - begin < 5)
    {
        char *psz_str;
        asprintf(&psz_str, "Took: %jus\tresult: %f", end - begin, j);
        puts(psz_str);
        return 0;
    }
    else
    {
        fprintf(stderr, "Computer too slow for this task!");
        return 1;
    }
}

It's obvious that this programming is leaking the memory allocated by asprintf but valgrind will not be able to see. Because of the slow down, the application will take the error path and not call asprintf:

$ valgrind --leak-check=full ./fail
[...]
Computer too slow for this task!
==6941==
==6941== HEAP SUMMARY:
==6941==     in use at exit: 0 bytes in 0 blocks
==6941==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==6941==
==6941== All heap blocks were freed -- no leaks are possible
[...]

Introducing timescaler

Principles

To work around this issue, I developed timescaler. This library hooks time-dependent functions exported by the libc to scale the time seen by the application. For instance, an application will call sleep(s) in order to sleep for s seconds and will in fact sleep for s*scaling seconds.

This scaling will compensate the slow down of the valgrind checks.

Basic examples

In the following basic example, we ask the process to sleep for 1 seconds while measuring the time with another process. In the second and third runs, timescaler is hooking the time-related functions:

$ time sleep 1
1.022 total
$ time env TIMESCALER_SCALE=2 LD_PRELOAD=timescaler.so sleep 1
2.003 total
$ time env TIMESCALER_SCALE=10 LD_PRELOAD=timescaler.so sleep 1
10.003 total

timescaler is using the LD_PRELOAD mechanism to hooks some functions form the libc. The time scaling is controlled be the environment variable TIMESCALER_SCALE. When set to 2, the time is running 2 times slower for the application than for the real world.

timescaler on VLC/Valgrind

Looking back at our first example with VLC media player under valgrind monitoring:

$ export TIMESCALER_SCALE=10 LD_PRELOAD=timescaler.so
$ valgrind --leak-check=full ./vlc -I dummy -A dummy video.mkv
[...]
VLC media player 2.1.0-git Rincewind (revision 1.3.0-git-3513-g970b2ac)
[0x710e7c8] dummy interface: using the dummy interface module...
[no avcodec errors]

VLC is no longer dropping images due to the slow down. If you look at the video that VLC is playing, you will see the video playing really slowly, images by images. But for VLC the video is playing at the right speed, without any pictures decoded too late.

Finding back our bugs

We can now try timescaler on our simple example and see if valgrind is now able to find the memory leak:

$ TIMESCALER_SCALE=10 LD_PRELOAD=timescaler.so valgrind --leak-check=full ./fail
[...]
The computation took: 1 seconds
result: 666666661666.567017
==6982==
==6982== HEAP SUMMARY:
==6982==     in use at exit: 93 bytes in 2 blocks
==6982==   total heap usage: 3 allocs, 1 frees, 193 bytes allocated
==6982==
==6982== 61 bytes in 1 blocks are definitely lost in loss record 2 of 2
==6982==    at 0x4C275A2: realloc (vg_replace_malloc.c:525)
==6982==    by 0x5320602: vasprintf (vasprintf.c:86)
==6982==    by 0x5304817: asprintf (asprintf.c:37)
==6982==    by 0x40079B: main (in /tmp/fail)
==6982==
==6982== LEAK SUMMARY:
==6982==    definitely lost: 61 bytes in 1 blocks
==6982==    indirectly lost: 0 bytes in 0 blocks
==6982==      possibly lost: 0 bytes in 0 blocks
==6982==    still reachable: 32 bytes in 1 blocks
==6982==         suppressed: 0 bytes in 0 blocks
==6982== Reachable blocks (those to which a pointer was found) are not shown.

As timescaler compensate the slow down of valgrind, the application behave normally and the leak is detected by valgrind.

Getting timescaler

The timescaler source code can be found on gihub.

timescaler only hooks a subset of the time-dependent libc functions that it can hooks. This subset is enough to scale the time of most applications including VLC media player. If you want to contribute to timescaler, do not hesitate to send mail, patches, pull request, bug reports ...


Making VLC at home

ven. 04 mai 2012 by Rémi Duraffort

In my previous article, I showed a way to setup and jump into a root file system in order to test a software in this environment.

Using PRoot, such task looks really easy and does not require any privileges. We will now finish this setup in order to build and …

read more

PRoot sorcery

lun. 16 avril 2012 by Rémi Duraffort

A good practice for software developer is to provide a test suite while developing a software. When developing for Linux, it's also a good practice to compile the software and run the test suite on many distributions like Debian, Ubuntu, Fedora, ArchLinux, Centos, Slackware and for both i386 and x86_64 …

read more

VLC on Android

mer. 02 février 2011 by Rémi Duraffort

A lot of people are asking about the status of VLC media player on Android. We usually answered that we are working on it. Now that some good progresses has been done, lets look at the current status of VLC media player for Android.

Current status

After two months of …

read more

Google Mentor Summit (part2)

jeu. 11 novembre 2010 by Rémi Duraffort

We went to the Google Mentor Summit in California for the week-end, let's talk a bit about it ...

The Google Mentor Summit

Every year, Google organizes the Google Summer of Code. This event is an opportunity for students to work on Open Source projects during the summer and being payed …

read more

VideoLAN accepted for Google Code In

sam. 06 novembre 2010 by Rémi Duraffort

Google just released the list of organizations that will participate to the Google Code In contest and VideoLAN is part of it!

Google Code In

I guess most people knows about the Google Summer of Code contest that Google runs every summer. For the one who don't know, every summer …

read more

Google Summer of Code: Mentor Summit

jeu. 21 octobre 2010 by Rémi Duraffort

Google Mentor Summit

A quick note to announce that we will be at the Google Mentor Summit in California this week-end. This meeting is organized by Google to close the Google Summer of Code and to meet developers from different Free Softwares projects.

Two developers from the VideoLAN project and …

read more

Compiling VLC for linux people

ven. 01 octobre 2010 by Rémi Duraffort

Compiling VLC media player on Linux is now something really easy. This article is a small tutorial for every people wondering about it.

VLC versions

First, you have to choose which version of VLC you would like to compile as at least two versions can be useful to compile

  • unstable …
read more

VLC media player extension for LibriVox

lun. 13 septembre 2010 by Rémi Duraffort

Thanks to VLC extensions, we recently created a script that fetch books from LibriVox. This website is a directory and a project that provide free audio books from the Public Domain like Frankenstein (Mary Shelley) or War and Peace (Leo Tolstoy).

LibriVox

LibriVox is a website in which you can …

read more

Free music and VLC

mer. 18 août 2010 by Rémi Duraffort

Actually more and more artists are following the Open Source movement and create really nice content (both audio and video). Since the latest release of VLC media player (1.1.0), thanks to VLC extensions, we added the ability to access selections of Free Music directly from the playlist. Let's …

read more