Skip to content

sixvid causes contour grief #408

@hackerb9

Description

@hackerb9

Description

Sixvid is an extremely simple GIF viewer for sixel terminals. For some reason Contour seems to be having trouble with it.

Environment

  • Contour Version or Git commit hash: github main 77cb600
  • Operating System (name / distribution / version): Debian GNU/Linux (bullseye)
  • Contour configuration: unchanged
  • TERM environment variable: unchanged
  • Compiler version: g++ 10

Steps to Reproduce

  1. git clone https://github.com/hackerb9/sixvid
  2. cd sixvid
  3. ./sixvid -b nyantocat.gif

Note that the -b option tells sixvid to run in "benchmark" mode, so it will loop the video as fast as possible.

Odd effects occur

  1. This test requires a terminal with enough space for a 500x500 image plus two lines of text. On XTerm with a 10x20 pixel font, dragging the terminal out to be 27 rows tall is sufficient.
    a. On Contour, that doesn't work. The sixel image is scaled and the screen scrolls on every frame.
    b. The scaling of the image is very peculiar. For example, I have portrait monitor (taller than wide) and the video appeared smooshed.
Smooshed nyantocat

image

  1. Trying to resize the font using Ctrl+mousewheel triggered two bugs.
    a. When I zoomed in, the terminal started using up 100% CPU (on one core) and the frame rate dropped to 1% of its previous level. Eventually Contour was so unresponsive I had to kill the process.
    b. I tried zooming out. This time I quit sixvid before zooming just in case that had caused a problem. At first the text and image were getting smaller, but then Contour crashed trying to free an invalid pointer.
(gdb) bt
free(): invalid pointer

Thread 1 "contour" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff649e537 in __GI_abort () at abort.c:79
#2  0x00007ffff64f7768 in __libc_message
    (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff6605e2d "%s\n")
    at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff64fea5a in malloc_printerr (str=str@entry=0x7ffff660405a "free(): invalid pointer")
    at malloc.c:5347
#4  0x00007ffff6500ca6 in free_check (mem=0x32e5470, caller=<optimized out>) at hooks.c:255
#5  0x00000000005669ca in __gnu_cxx::new_allocator<unsigned char>::deallocate(unsigned char*, unsigned long) (__t=<optimized out>, __p=<optimized out>, this=0x39a1900)
    at /usr/include/c++/10/ext/new_allocator.h:133
#6  std::allocator_traits<std::allocator<unsigned char> >::deallocate(std::allocator<unsigned char>&, unsigned char*, unsigned long) (__n=<optimized out>, __p=<optimized out>, __a=...)
    at /usr/include/c++/10/bits/alloc_traits.h:492
#7  std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate(unsigned char*, unsigned long) (__n=<optimized out>, __p=<optimized out>, this=0x39a1900)
    at /usr/include/c++/10/bits/stl_vector.h:354
#8  std::_Vector_base<unsigned char, std::allocator<unsigned char> >::~_Vector_base()
    (this=0x39a1900, __in_chrg=<optimized out>) at /usr/include/c++/10/bits/stl_vector.h:335
#9  std::vector<unsigned char, std::allocator<unsigned char> >::~vector()
    (this=0x39a1900, __in_chrg=<optimized out>) at /usr/include/c++/10/bits/stl_vector.h:683
#10 terminal::renderer::atlas::UploadTexture::~UploadTexture()
    (this=0x39a18f8, __in_chrg=<optimized out>)
    at src/contour/src/contour/opengl/../../terminal_renderer/Atlas.h:115
#11 std::_Destroy<terminal::renderer::atlas::UploadTexture>(terminal::renderer::atlas::UploadTexture*) (__pointer=0x39a18f8) at /usr/include/c++/10/bits/stl_construct.h:140
--Type <RET> for more, q to quit, c to continue without paging--c
#12 std::_Destroy_aux<false>::__destroy<terminal::renderer::atlas::UploadTexture*>(terminal::renderer::atlas::UploadTexture*, terminal::renderer::atlas::UploadTexture*) (__last=<optimized out>, __first=0x39a18f8) at /usr/include/c++/10/bits/stl_construct.h:152
#13 std::_Destroy<terminal::renderer::atlas::UploadTexture*>(terminal::renderer::atlas::UploadTexture*, terminal::renderer::atlas::UploadTexture*) (__last=<optimized out>, __first=<optimized out>) at /usr/include/c++/10/bits/stl_construct.h:185
#14 std::_Destroy<terminal::renderer::atlas::UploadTexture*, terminal::renderer::atlas::UploadTexture>(terminal::renderer::atlas::UploadTexture*, terminal::renderer::atlas::UploadTexture*, std::allocator<terminal::renderer::atlas::UploadTexture>&) (__last=<optimized out>, __first=<optimized out>) at /usr/include/c++/10/bits/alloc_traits.h:738
#15 std::vector<terminal::renderer::atlas::UploadTexture, std::allocator<terminal::renderer::atlas::UploadTexture> >::_M_erase_at_end(terminal::renderer::atlas::UploadTexture*) (__pos=<optimized out>, this=<optimized out>) at /usr/include/c++/10/bits/stl_vector.h:1796
#16 std::vector<terminal::renderer::atlas::UploadTexture, std::allocator<terminal::renderer::atlas::UploadTexture> >::clear() (this=<optimized out>) at /usr/include/c++/10/bits/stl_vector.h:1499
#17 terminal::renderer::opengl::OpenGLRenderer::executeRenderTextures() (this=this@entry=0xe6efb0) at src/contour/src/contour/opengl/OpenGLRenderer.cpp:696
#18 0x0000000000566c6e in operator() (__closure=<optimized out>) at src/contour/src/contour/opengl/OpenGLRenderer.cpp:647
#19 terminal::renderer::opengl::bound<QOpenGLShaderProgram, terminal::renderer::opengl::OpenGLRenderer::execute()::<lambda()> > (_callable=<optimized out>, _bindable=...) at src/contour/src/contour/opengl/OpenGLRenderer.cpp:197
#20 terminal::renderer::opengl::OpenGLRenderer::execute() (this=0xe6efb0) at src/contour/src/contour/opengl/OpenGLRenderer.cpp:644
#21 0x0000000000573c3e in terminal::renderer::Renderer::render(terminal::Terminal&, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >, bool) (this=this@entry=0x70e488, _terminal=..., _now=..., _pressure=_pressure@entry=false) at src/contour/src/terminal_renderer/Renderer.cpp:301
#22 0x00000000005600e7 in contour::opengl::TerminalWidget::paintGL() (this=0x70e400) at src/contour/src/contour/opengl/TerminalWidget.cpp:455
#23 0x00007ffff7952c5d in  () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007ffff7934fae in QWidget::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x0000000000563738 in contour::opengl::TerminalWidget::event(QEvent*) (this=0x70e400, _event=0x7fffffffc900) at src/contour/src/contour/opengl/TerminalWidget.cpp:577
#26 0x00007ffff78f515f in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#27 0x00007ffff6c18fca in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#28 0x00007ffff792d116 in QWidgetPrivate::sendPaintEvent(QRegion const&) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#29 0x00007ffff792d962 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#30 0x00007ffff792ecb3 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#31 0x00007ffff792ead2 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#32 0x00007ffff792d67c in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#33 0x00007ffff792ecb3 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#34 0x00007ffff792d67c in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#35 0x00007ffff790586a in  () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#36 0x00007ffff79356d7 in QWidget::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#37 0x00007ffff78f515f in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#38 0x00007ffff6c18fca in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#39 0x00007ffff6c1ba01 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#40 0x00007ffff6c70e93 in  () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#41 0x00007ffff62a3e6b in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#42 0x00007ffff62a4118 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#43 0x00007ffff62a41cf in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#44 0x00007ffff6c7051f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#45 0x00007ffff6c1798b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#46 0x00007ffff6c1fc00 in QCoreApplication::exec() () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#47 0x00000000004d71ee in contour::terminalGUI(int, char const**, crispy::cli::FlagStore const&) (argc=<optimized out>, argv=0x7fffffffe618, _flags=...) at src/contour/src/contour/ContourGuiApp.cpp:188
#48 0x00000000005807d4 in std::function<int ()>::operator()() const (this=0x666230) at /usr/include/c++/10/bits/std_function.h:622
#49 crispy::App::run(int, char const**) (this=this@entry=0x7fffffffe340, argc=argc@entry=1, argv=argv@entry=0x7fffffffe618) at src/contour/src/crispy/App.cpp:242
#50 0x00000000004d4fa2 in contour::ContourGuiApp::run(int, char const**) (this=this@entry=0x7fffffffe340, argc=argc@entry=1, argv=argv@entry=0x7fffffffe618) at src/contour/src/contour/ContourGuiApp.cpp:52
#51 0x000000000048f0db in main(int, char const**) (argc=1, argv=0x7fffffffe618) at src/contour/src/contour/main.cpp:24
(gdb) 
  1. Just running sixvid without resizing anything, usually works. But I did have a weird heisenbug that only appeared when I wasn't looking for it. The video would intermittently blank out. It would show the animation for a couple seconds and then a black screen for a couple seconds. I turned off benchmarking by hitting the letter b and was surprised to see that the blanking duty cycle seemed the same whether I was sending 33 frames per second or 133 frames per second.
    a. I was unable to reliably reproduce this problem. I had it happen three times, but each time I thought I knew what had triggered it, I was wrong.
    b. It is possible it has something to do with prior tests of sixvid that I had done in the same Contour window.

  2. Sometimes after quitting sixvid and then running it again, Contour uses up 100% CPU (again on only one core) for around 10 seconds before showing even the first frame. While it is normal for sixvid to use up some CPU while decoding the video, the terminal itself should not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    VT: BackendVirtual Terminal Backend (libterminal API)

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions