summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS10
-rw-r--r--libguile-ssh/channel-type.c28
-rw-r--r--tests/client-server.scm19
3 files changed, 45 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 50b2275..397c653 100644
--- a/NEWS
+++ b/NEWS
@@ -13,7 +13,15 @@ Copyright (C) Artyom V. Poptsov <poptsov.artyom@gmail.com>
**** 'node-guile-version' now does not fail
The procedure would always fail to get Guile version. Now that should be
fixed.
-** Update uit tests
+*** In (ssh channel)
+**** Printing a freed channel doesn't lead to SIGSEGV anymore
+ Guile-SSH would always crash with SIGSEGV errors when tried to print a
+ freed channel object (e.g. after calling 'close' on a channel). This bug
+ is fixed now by introducing new checks.
+
+ Now a freed channel will be printed like this:
+ #<unknown channel (freed) 9412f0>
+** Update unit tests
*** Add test cases for fixed bugs
* Changes in version 0.11.1 (2017-05-09)
diff --git a/libguile-ssh/channel-type.c b/libguile-ssh/channel-type.c
index 3dd641f..cc9dae6 100644
--- a/libguile-ssh/channel-type.c
+++ b/libguile-ssh/channel-type.c
@@ -1,6 +1,6 @@
/* channel-type.c -- SSH channel smob.
*
- * Copyright (C) 2013, 2014, 2015 Artyom V. Poptsov <poptsov.artyom@gmail.com>
+ * Copyright (C) 2013, 2014, 2015, 2016, 2017 Artyom V. Poptsov <poptsov.artyom@gmail.com>
* Copyright (C) 2017 Ludovic Courtès <ludo@gnu.org>
*
* This file is part of Guile-SSH.
@@ -244,24 +244,30 @@ ptob_close (SCM channel)
static int
print_channel (SCM channel, SCM port, scm_print_state *pstate)
{
- struct channel_data *ch = _scm_to_channel_data (channel);
+ struct channel_data *ch = NULL;
+
+ if (SCM_PTAB_ENTRY (channel))
+ ch = _scm_to_channel_data (channel);
scm_puts ("#<", port);
- scm_print_port_mode (channel, port);
- scm_puts ("channel ", port);
if (! ch)
{
- scm_puts ("(freed) ", port);
- }
- else if (SCM_OPPORTP (channel))
- {
- int is_open = ssh_channel_is_open (ch->ssh_channel);
- scm_puts (is_open ? "(open) " : "(closed) ", port);
+ scm_puts ("unknown channel (freed) ", port);
}
else
{
- scm_puts ("(closed) ", port);
+ scm_print_port_mode (channel, port);
+ scm_puts ("channel ", port);
+ if (SCM_OPPORTP (channel))
+ {
+ int is_open = ssh_channel_is_open (ch->ssh_channel);
+ scm_puts (is_open ? "(open) " : "(closed) ", port);
+ }
+ else
+ {
+ scm_puts ("(closed) ", port);
+ }
}
scm_display (_scm_object_hex_address (channel), port);
scm_puts (">", port);
diff --git a/tests/client-server.scm b/tests/client-server.scm
index b56a329..702cd3a 100644
--- a/tests/client-server.scm
+++ b/tests/client-server.scm
@@ -23,6 +23,7 @@
(srfi srfi-26)
(ice-9 threads)
(ice-9 rdelim)
+ (ice-9 regex)
(rnrs bytevectors)
(rnrs io ports)
(ssh server)
@@ -585,6 +586,24 @@
(channel-request-exec channel "uname")
(channel-get-exit-status channel)))))))
+(test-assert-with-log "channel-request-exec, printing a freed channel"
+ (run-client-test
+
+ ;; server
+ (lambda (server)
+ (start-server/channel-test server))
+
+ ;; client
+ (lambda ()
+ (call-with-connected-session/channel-test
+ (lambda (session)
+ (let ((channel (make-channel session)))
+ (channel-open-session channel)
+ (channel-request-exec channel "uname")
+ (close channel)
+ (string-match "#<unknown channel \\(freed\\) [0-9a-f]+>"
+ (object->string channel))))))))
+
;; data transferring
;; FIXME: Probably these TCs can be implemented more elegantly.