tag 886496 patch thanks.
On 07.01.2019 18:50, Bernhard Übelacker wrote: > Dear Maintainer, > I tried to have a look at this segfault. > > It seems this is a case of pointer truncation. Thanks for finding the problem! Now that I knew where to look, I made a patch to store the pointer in a separate array and only pass an index into that array to the backend. With an error message if the array exceeds the maximum size representable by an int... I tested it in the stable package and so far it worked. I used these for testing (particularly against memory leaks): perl -e 'use OpenGL ":all"; glutInit(); glutCreateWindow("title"); sub queue { my ($time,$id) = @_; glutTimerFunc($time,sub{ print $id,"\n"; queue($time,$id); }); } for (1..1000) { queue(sqrt($_),$_); } glutMainLoop();' ---> using "top", check that resident set size stops growing. perl -e '$|=1; use List::Util "shuffle"; use OpenGL ":all"; glutInit(); glutCreateWindow("title"); my @arr = shuffle(1..1000); for my $x (@arr) { glutTimerFunc($x*10,sub{ print $x,"\n"; }); } glutMainLoop();' | tee foo.txt perl -ne 'BEGIN{$i=0} print if $_ != ($i+1); $i = $_' < foo.txt ---> check, that the callbacks are not mixed up. (There may be irregularities if the event times are close to each other) perl -e 'use OpenGL ":all"; glutInit(); glutCreateWindow("title"); for my $x (0..66553) { glutTimerFunc(1000,sub{ print $x,"\n"; }); } glutMainLoop();' ---> Many concurrent timers need a lot of time and memory, but I think that is more due to the backend than due to my array... Also, it's still linear time and memory. One of these days, someone's got to show me how to work *with* quilt rather than against it... Yours Thomas -- OpenPGP Key ID: 0x6BFFE5CF3C7720398928CE741F2DAE97486A60BF
Description: Fix https://bugs.debian.org/886496 * Patched pogl_glut.xs to fix pointer truncation in glutTimerFunc (Closes: #886496) Author: Thomas Kremer <bugs.deb...@xorg.c-informatik.de> Bug-Debian: https://bugs.debian.org/886496 Last-Update: 2019-01-23 --- libopengl-perl-0.6704+dfsg.orig/pogl_glut.xs +++ libopengl-perl-0.6704+dfsg/pogl_glut.xs @@ -440,10 +440,27 @@ static void generic_glut_Close_handler(v DO_perl_call_sv(handler, G_DISCARD); } +/* glut_timer_handlers is an allocation buffer. + All unused elements are SVivs forming a linked-list, + starting at glut_timer_handlers_next_free. + The end of the list is marked by a -1. + If no element is free when one is needed, the buffer will grow. +*/ +static AV * glut_timer_handlers = 0; +static int glut_timer_handlers_next_free = -1; + /* Callback for glutTimerFunc */ static void generic_glut_timer_handler(int value) { - AV * handler_data = (AV*)value; + if (!glut_timer_handlers) + croak("Timer handler called, but no timers have ever been set up"); + SV** h = av_fetch(glut_timer_handlers,value,FALSE); + if (!h || !SvOK(*h) || !SvROK(*h)) + croak("Timer handler called for unregistered timer"); + AV * handler_data = (AV*)SvRV(*h); + sv_setiv(*h,glut_timer_handlers_next_free); + glut_timer_handlers_next_free = value; + SV * handler; int i; dSP; @@ -1016,8 +1033,24 @@ glutTimerFunc(msecs, handler=0, ...) AV * handler_data = newAV(); PackCallbackST(handler_data, 1); + SV * handler_data_sv = newRV_inc((SV*)handler_data); - glutTimerFunc(msecs, generic_glut_timer_handler, (int)handler_data); + if (!glut_timer_handlers) + glut_timer_handlers = newAV(); + + int handler_id = glut_timer_handlers_next_free; + if (handler_id == -1) { + handler_id = ((int) av_top_index(glut_timer_handlers))+1; + if (handler_id < 0) + croak("Limit of concurrent timers reached (MAX_INT)"); + av_push(glut_timer_handlers, handler_data_sv); + } else { + SV** entry = av_fetch(glut_timer_handlers,handler_id,FALSE); + glut_timer_handlers_next_free = SvIV(*entry); + sv_setsv(*entry,sv_2mortal(handler_data_sv)); + } + + glutTimerFunc(msecs, generic_glut_timer_handler, handler_id); } ENSURE_callback_thread;}