Control: tags 843568 + patch

On Mon 2016-11-07 14:57:10 -0500, Daniel Kahn Gillmor wrote:
> With no ~/.TinyCA at all, try running:
>
>     tinyca2
>
> hit cancel in the "Create a new CA" dialog box which pops up, and then
> click the "Quit"  button in the toolbar.
>
> The result is:
>
>     Segmentation fault

on IRC, i learned:

08:22 <bleve> Hello, I found out debian bug 
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=843568
08:22 <bleve> Just wanted to let you know that ubuntu bug has a fix for the 
issue: https://bugs.launchpad.net/ubuntu/+source/tinyca/+bug/1545276
08:23 <bleve> 
https://github.com/abone28/tinyca/commit/607e5477c756fb2214ee01f8e8e49e8d7b984b39
 fixes the issue.

I'm attaching the patch here, though i haven't tested it (i no longer
use tinyca myself).

Thanks to bleve and abone for the review and the work, though!

       --dkg

From 607e5477c756fb2214ee01f8e8e49e8d7b984b39 Mon Sep 17 00:00:00 2001
From: Andrey Bondarenko <abon...@mail.ru>
Date: Sun, 21 Jan 2018 02:22:52 +0500
Subject: [PATCH] do not call exit() in gtk main loop

Perl exit() called in signal while GTK main loop is active
may cause segmentation fault. Signal handlers should not
call exit directly. Now they set global exit code and ask
GTK main loop to stop. Main will call exit after end of
GTK main loop.
---
 lib/CA.pm      |  2 +-
 lib/GUI.pm     |  4 ++--
 lib/HELPERS.pm | 63 ++++++++++++++++++++++++++++++++++++++------------
 tinyca2        |  6 ++---
 4 files changed, 53 insertions(+), 22 deletions(-)

diff --git a/lib/CA.pm b/lib/CA.pm
index f1f2407..02f59ed 100644
--- a/lib/CA.pm
+++ b/lib/CA.pm
@@ -42,7 +42,7 @@ sub new {
 
    opendir(DIR, $self->{'init'}->{'basedir'}) || do {
       print _("error: can't open basedir: ").$!;
-      exit(1);
+      HELPERS::exit_clean(1);
    };
 
    $self->{'calist'} = [];
diff --git a/lib/GUI.pm b/lib/GUI.pm
index 9cab38a..5400603 100644
--- a/lib/GUI.pm
+++ b/lib/GUI.pm
@@ -448,7 +448,7 @@ sub create_toolbar {
       $button = Gtk2::ToolButton->new_from_stock('gtk-quit');
       $self->{'toolbar'}->insert($button, -1);
       $button->set_tooltip_text(_('Quit TinyCA'));
-      $button->signal_connect('clicked', sub { exit(4) });
+      $button->signal_connect('clicked', sub { HELPERS::exit_clean(4) });
 
 
       $button = Gtk2::ToolButton->new_from_stock('gtk-open');
@@ -697,7 +697,7 @@ sub create_menu {
                item_type => '<Separator>',
             },
             _("_Exit") => {
-               callback    => sub { exit(3) },
+               callback    => sub { HELPERS::exit_clean(3) },
                item_type   => '<StockItem>',
                extra_data  => 'gtk-close'
             }
diff --git a/lib/HELPERS.pm b/lib/HELPERS.pm
index 91d894a..c93dfe9 100644
--- a/lib/HELPERS.pm
+++ b/lib/HELPERS.pm
@@ -76,22 +76,47 @@ sub mktmp {
 }
 
 
+
+our $retcode = 0; # Global variable for app return code
+our $in_main = 0; # Flag is 1 if app is in Gtk->main_loop
+
+#
+# Run Gtk->main_loop()
+#
+sub main_loop {
+    our $in_main;
+    $in_main = 1;
+    Gtk2->main();
+    $in_main = 0;
+}
+
 #
 # finished...
 #
 sub exit_clean {
-   my ($ret) = @_;
-
-   $ret = 0 unless(defined $ret);
-   
-   # hack to avoid busy cursor
-   my $rootwin = Gtk2::Gdk->get_default_root_window();
-   my $cursor  = Gtk2::Gdk::Cursor->new('left-ptr');
-
-   $rootwin->set_cursor($cursor);
-   
-   Gtk2->main_quit();
-   exit($ret);
+    my ($ret) = @_;
+
+    # save return code passed in arg to global variable
+    our $retcode;
+    if (defined $ret) {
+        $retcode = $ret;
+    }
+
+    our $in_main;
+    if ( $in_main ) {
+        # Calling exit() when GTK main loop is active may cause segfault.
+        # Exiting loop and let main thread terminate application later.
+        Gtk2->main_quit();
+    } else {
+        # hack to avoid busy cursor
+        my $rootwin = Gtk2::Gdk->get_default_root_window();
+        my $cursor  = Gtk2::Gdk::Cursor->new('left-ptr');
+        $rootwin->set_cursor($cursor);
+
+        # exit() when Gtk main loop is not active is safe
+        exit($retcode);
+    }
+
 }
 
 #
@@ -284,7 +309,8 @@ HELPERS - helper functions for TinyCA, doing small jobs not related to the GUI
    $dnhash  = HELPERS::parse_dn($dnstring);
    $exthash = HELPERS::parse_extensions($mode, $lines);
    $subjaltname = HELPERS::gen_subjectaltname_contents($type, @list);
-   
+
+   main_loop();
    exit_clean($retcode);
 
 =head1 DESCRIPTION
@@ -347,12 +373,19 @@ data.
 
 =back
 
+=head2 HELPERS::main_loop()
+
+=over 1
+
+wrapper around Gtk->main_loop()
+
+=back
+
 =head2 HELPERS::exit_clean($retcode)
 
 =over 1
 
-does nothing yet, than closing the Gtk application returning the exitcode
-given in $retcode.
+close the Gtk application and return the exitcode given in $retcode.
 
 =back
 
diff --git a/tinyca2 b/tinyca2
index 0a161b9..2014450 100755
--- a/tinyca2
+++ b/tinyca2
@@ -143,7 +143,5 @@ sub _ {
    return($s);
 }
 
-Gtk2->main();
-
-exit(0);
-
+HELPERS::main_loop();
+HELPERS::exit_clean();
-- 
2.20.1

Attachment: signature.asc
Description: PGP signature

Reply via email to