It seems I've angered the god of threads, after years of him benevolently observing my adventures.

I've updated my machines from openSUSE 15.6 to 16.0, which brought about system perl's jump from 5.26.1 to 5.42.0.

I can't run my PerlMonks ChatterBox GUI client with threads anymore. It seems Time::Piece is no longer thread safe. I'm getting random segmentation faults and errors from Tk with missing characters, e.g.

Tk::Error: bad text index "5.96" at /usr/lib/perl5/vendor_perl/5.42.0/ +x86_64-linux-thread-multi/Tk.pm line 251. k callback for .frame.rotext k::After::repeat at /usr/lib/perl5/vendor_perl/5.42.0/x86_64-linux-th +read-multi/Tk/After.pm line 80 [repeat,[{},after#45,1000,repeat,[\&PM::CB::GUI::__ANON__]]]
which seems like there are strange things going on in the memory.

Fortunately, MCE works without problems, so I still have 2 possible ways how to run the client.

I know I'm no genius. It's possible the bug had been there in my code all the time and something just awakened it. So far, I haven't been able to simplify the code to reproduce the errors without all the non-related logic involved.

(Tested with Tk 804.036, Time::Piece both 1.36 and 1.41).

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re: Threads, Tk, Time, oh my!
by Corion (Patriarch) on May 07, 2026 at 07:43 UTC

    It seems that in your code, the only (relevant?) use of Time::Piece is in PM::CB::Communication for the timestamp. But you only use Time::Piece there to parse the incoming create time and convert it to some other string. This should be fairly safe, but maybe mod:://Time::Piece runs afoul of setting/resetting timezones or locale data between threads.

    Does the problem go away if you switch from Time::Piece to POSIX::strftime and manually convert the string (resp. replace the string with a hardcoded dummy)?

    if (@nodes) { $self->{to_gui}->enqueue( [private => '<pm-cb-g>', 'Time::Piece'->strptime($_->{createtime}, '%Y%m%d%H%M%S') ->strftime('%Y-%m-%d %H:%M:%S'), "New node: [id://$_->{node_id}|" . $_->textContent =~ s/\n//r . '] by [id://' . "$_->{author_user}|$_->{authortitle} +]", NOT_DELETABLE]) for grep ! exists $nodes{ $_->{node_id} }, reverse @no +des; @nodes{ map $_->{node_id}, @nodes} = (); }

    Alternatively, you can maybe try to run your code with $ENV{LANG}='C' or $ENV{LC_TIME}='C', or whatever is used to reset the information there... If that "helps", this points towards a locale handling bug/conflict between threads and Time::Piece, but that's where my ideas end.

      > the only (relevant?) use of Time::Piece is in PM::CB::Communication for the timestamp

      Unfortunately, there's far more of Time::Piece in PM::CB::GUI.

      Thanks for the recommendations and tips, I'll experiment with them and see.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        Aah - yeah, this part looks fishy, or at least prone to trigger thread+locale-based conflicts:

        if (defined $time) { local $ENV{TZ} = 'America/New_York'; my $est = Time::Piece::localtime()->tzoffset; $time = 'Time::Piece'->strptime($time, '%Y-%m-%d %H:%M:%S') - $est + $tzoffset; } else {

        Manipulating the timezone is weirdly(?) not threadsafe, or at least that's what I remember from some Perl tickets.

        Update: You could calculate the timezone once at program startup, that could eliminate the switching of the timezone within a thread.