[vlc-devel] libvlc crashes on Windows when an application call libvlc_media_player_stop()

Ori Pessach mail at oripessach.com
Sun Apr 21 21:39:27 CEST 2019


I've seen this in every version of libvlc I tested since 3.0.1, including
3.0.6. I tried the Win32 and Win64 builds, and both seem to have the same
issue.

I have an application that displays multiple RTSP streams, and it
occasionally crashes when calling libvlc_media_player_stop(). Here's the
backtrace:

Thread 1397 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 9080.0x1904]
av_buffer_unref (buf=buf at entry=0x1b7e804c2c0) at libavutil/buffer.c:130
130     libavutil/buffer.c: No such file or directory.
(gdb) bt
#0  av_buffer_unref (buf=buf at entry=0x1b7e804c2c0) at libavutil/buffer.c:130
#1  0x00007ffcfc2f733b in ff_dxva2_decode_uninit (avctx=<optimized out>) at
libavcodec/dxva2.c:727
#2  0x00007ffcfc433a32 in avcodec_close (avctx=avctx at entry=0x1b785586a80)
at libavcodec/utils.c:1171
#3  0x00007ffcfbd10799 in avcodec_free_context (pavctx=0x60d29f288) at
libavcodec/options.c:179
#4  0x00007ffcfb8b4e9c in EndVideoDec (obj=<optimized out>) at
../../extras/package/win32/../../../modules/codec/avcodec/video.c:1275
#5  0x00007ffd066a803a in vlc_module_unload (obj=obj at entry=0x1b7a417ba00,
module=<optimized out>,
    deinit=deinit at entry=0x7ffd066a76f0 <generic_stop>) at
../../extras/package/win32/../../../src/modules/modules.c:343
#6  0x00007ffd066a8105 in module_unneed (obj=obj at entry=0x1b7a417ba00,
module=<optimized out>)
    at ../../extras/package/win32/../../../src/modules/modules.c:378
#7  0x00007ffd066c48c6 in UnloadDecoder (p_dec=p_dec at entry=0x1b7a417ba00)
at ../../extras/package/win32/../../../src/input/decoder.c:201
#8  0x00007ffd066c5233 in DeleteDecoder (p_dec=0x1b7a417ba00) at
../../extras/package/win32/../../../src/input/decoder.c:1818
#9  0x00007ffd066c885a in input_DecoderDelete (p_dec=<optimized out>) at
../../extras/package/win32/../../../src/input/decoder.c:2020
#10 0x00007ffd066caac9 in EsDestroyDecoder (p_es=<optimized out>,
p_es=<optimized out>, out=0x1b7c2031fe0)
    at ../../extras/package/win32/../../../src/input/es_out.c:1713
#11 0x00007ffd066cc0f1 in EsUnselect (out=out at entry=0x1b7c2031fe0,
es=0x1b7f241baa0, b_update=<optimized out>)
    at ../../extras/package/win32/../../../src/input/es_out.c:1841
#12 0x00007ffd066cf565 in EsOutControlLocked (args=<optimized out>,
i_query=<optimized out>, out=0x1b7c2031fe0)
    at ../../extras/package/win32/../../../src/input/es_out.c:2323
#13 EsOutControl (out=0x1b7c2031fe0, i_query=<optimized out>,
args=<optimized out>)
    at ../../extras/package/win32/../../../src/input/es_out.c:2900
#14 0x00007ffd066d1cb3 in es_out_vaControl (args=0x60d29f620 "",
i_query=<optimized out>, out=<optimized out>)
    at ../../extras/package/win32/../../../include/vlc_es_out.h:141
#15 es_out_Control (out=<optimized out>, i_query=<optimized out>) at
../../extras/package/win32/../../../include/vlc_es_out.h:150
#16 0x00007ffd066d372e in ControlLocked (args=<optimized out>,
i_query=<optimized out>, p_out=<optimized out>)
    at ../../extras/package/win32/../../../src/input/es_out_timeshift.c:664
#17 Control (p_out=<optimized out>, i_query=<optimized out>,
args=<optimized out>)
    at ../../extras/package/win32/../../../src/input/es_out_timeshift.c:764
#18 0x00007ffd066d5383 in es_out_vaControl (args=0x60d29f740 "",
i_query=65536, out=<optimized out>)
    at ../../extras/package/win32/../../../include/vlc_es_out.h:141
#19 es_out_Control (out=<optimized out>, i_query=i_query at entry=65536) at
../../extras/package/win32/../../../include/vlc_es_out.h:150
#20 0x00007ffd066d5fab in es_out_SetMode (i_mode=0, p_out=<optimized out>)
at ../../extras/package/win32/../../../src/input/es_out.h:95
#21 End (p_input=p_input at entry=0x1b79d4b85e0) at
../../extras/package/win32/../../../src/input/input.c:1484
#22 0x00007ffd066dd9ab in Run (data=0x1b79d4b85e0) at
../../extras/package/win32/../../../src/input/input.c:508
#23 0x00007ffd0672a516 in vlc_entry (p=0x1b79163b6d0) at
../../extras/package/win32/../../../src/win32/thread.c:470
#24 0x00007ffd3601aa96 in msvcrt!_beginthreadex () from
/cygdrive/c/WINDOWS/System32/msvcrt.dll
#25 0x00007ffd3601ab6c in msvcrt!_endthreadex () from
/cygdrive/c/WINDOWS/System32/msvcrt.dll
#26 0x00007ffd357e4034 in KERNEL32!BaseThreadInitThunk () from
/cygdrive/c/WINDOWS/System32/KERNEL32.DLL
#27 0x00007ffd383b3691 in ntdll!RtlUserThreadStart () from
/cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#28 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

I was able to work around this by patching the libavcodec_plugin code to
effectively disable hardware acceleration, but due to the number of RTSP
streams that the application needs to support, this isn't an ideal
solution.

I'm able to reproduce this problem with the attached program. It might seem
long, but most of the code is just Windows boilerplate. The interesting bit
is in the RunTests() function, which isn't very long.

By the way, the Win64 debug symbols that are available for download on
videolan.org don't seem to match the released code... I had to recompile
VLC myself to be able to get a stack trace from gdb.

I can make the entire Visual Studio project available if it's necessary,
but I didn't want to send binary files to the mailing list.

Any ideas what's going on here?

Thanks,

Ori Pessach
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20190421/e764f1b3/attachment-0001.html>
-------------- next part --------------
// vlc-crash.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "vlc-crash.h"
typedef SSIZE_T ssize_t;
#include "vlc/vlc.h"
#include <thread>

using namespace std;

constexpr auto NUM_PLAYERS = (18);

void RunTests();

thread *testThread=NULL;
libvlc_instance_t *instance=NULL;
libvlc_media_player_t *players[NUM_PLAYERS];

void playerPlayingCB(const struct libvlc_event_t *, void *self)
{

}

void playerVoutCB(const struct libvlc_event_t *, void *self)
{

}

void playerErrorCB(const struct libvlc_event_t *, void *self)
{

}

void playerTimeChangedCB(const struct libvlc_event_t *, void *self)
{

}

void playerStoppedCB(const struct libvlc_event_t *, void *self)
{

}

void RunTests()
{
	char *argv[]{ (char*)"libvlc", (char*)"--avcodec-hw=d3d11va"};
	instance = libvlc_new(2, argv);
	for (int i = 0; i < NUM_PLAYERS; i++) {
		players[i] = libvlc_media_player_new(instance);
		libvlc_event_manager_t *event_manager = libvlc_media_player_event_manager(players[i]);
		libvlc_event_attach(event_manager, libvlc_MediaPlayerPlaying, &playerPlayingCB, NULL);
		libvlc_event_attach(event_manager, libvlc_MediaPlayerVout, &playerVoutCB, NULL);
		libvlc_event_attach(event_manager, libvlc_MediaPlayerEncounteredError, &playerErrorCB, NULL);
		libvlc_event_attach(event_manager, libvlc_MediaPlayerTimeChanged, &playerTimeChangedCB, NULL);
		libvlc_event_attach(event_manager, libvlc_MediaPlayerStopped, &playerStoppedCB, NULL);
	}

	int n = 0;
	while (TRUE) {
		libvlc_media_t *media = NULL;

		if (libvlc_media_player_is_playing(players[n % NUM_PLAYERS])) {
			libvlc_media_player_stop(players[n % NUM_PLAYERS]);
		}

		media = libvlc_media_new_location(instance, "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov");
		//media = libvlc_media_new_location(instance, "rtsp://192.168.3.112/media/video1");
		//media = libvlc_media_new_location(instance, "rtsp://service:password@172.22.9.67");
		libvlc_media_player_set_media(players[n % NUM_PLAYERS], media);
		libvlc_media_player_play(players[n % NUM_PLAYERS]);
		libvlc_media_release(media);
		this_thread::sleep_for(chrono::milliseconds(50));
		n++;
	}
}

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
BOOL bTesting = FALSE;

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_VLCCRASH, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_VLCCRASH));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_VLCCRASH));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_VLCCRASH);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void StartTest(HWND hWnd)
{
	if (!bTesting) {
		testThread = new thread(RunTests);
		bTesting = TRUE;
		RECT r;
		GetClientRect(hWnd, &r);
		InvalidateRect(hWnd, &r, TRUE);
		UpdateWindow(hWnd);
	}
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
			case ID_ACTIONS_STARTTEST:
				StartTest(hWnd);
				break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
			if (bTesting) {
				RECT r;
				GetClientRect(hWnd, &r);
				TCHAR text[] = TEXT("Testing");
				TextOut(hdc, r.left+10, r.top+10, text, ARRAYSIZE(text));
			}
			EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


More information about the vlc-devel mailing list