summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--NEWS4
-rw-r--r--ssh/channel-type.c5
-rw-r--r--ssh/channel-type.h6
-rw-r--r--ssh/message-func.c2
-rw-r--r--ssh/message-type.h4
-rw-r--r--ssh/server-func.c2
7 files changed, 40 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 17939c9..9699d6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2014-06-06 Artyom Poptsov <poptsov.artyom@gmail.com>
+
+ Fix a GC issue: Keep a reference to the parent session in channel and
+ message smobs to prevent the session from premature GC'ing. Without
+ the fix GC could free a session even if there are live channels and by
+ that break the channels.
+
+ Reported by Ludovic Courtès <ludo@gnu.org>
+
+ * ssh/channel-type.h (channel_data): Store a reference to the parent
+ session.
+ * ssh/message-type.h (message_data): Likewise.
+ * ssh/channel-type.c (_ssh_channel_to_scm): Change argument list. All
+ callers updated.
+ (guile_ssh_make_channel): Update.
+ * ssh/message-func.c
+ (guile_ssh_message_channel_request_open_reply_accept): Update.
+ * ssh/server-func.c (guile_ssh_server_message_get): Store a reference
+ to a session in the message smob.
+ * NEWS: Update.
+
2014-06-01 Artyom Poptsov <poptsov.artyom@gmail.com>
* tests/key.scm: New test suite.
diff --git a/NEWS b/NEWS
index 2ab30a5..082bce8 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ Copyright (C) Artyom V. Poptsov <poptsov.artyom@gmail.com>
** New `bytevector->hex-string' procedure in (ssh key)
** Add tests for Guile-SSH keys
** Bug fixes
+*** Fix a GC issue
+ Keep a reference to the parent session in channels and messages to prevent
+ the session from premature GC'ing. Without that GC could free a session
+ even if there are live channels and by that break the channels.
*** `public-key?' and `private-key?' now produce correct result
Functions now return `#f' if the given argument is not a Guile-SSH
key object.
diff --git a/ssh/channel-type.c b/ssh/channel-type.c
index 2da0bd9..0c8dc70 100644
--- a/ssh/channel-type.c
+++ b/ssh/channel-type.c
@@ -194,7 +194,7 @@ print_channel (SCM channel, SCM port, scm_print_state *pstate)
/* Pack the SSH channel CH to a Scheme port and return newly created
port. */
SCM
-_ssh_channel_to_scm (ssh_channel ch)
+_ssh_channel_to_scm (ssh_channel ch, SCM session)
{
struct channel_data *channel_data;
SCM ptob;
@@ -204,6 +204,7 @@ _ssh_channel_to_scm (ssh_channel ch)
channel_data->ssh_channel = ch;
channel_data->is_stderr = 0; /* Reading from stderr disabled by default */
+ channel_data->session = session;
ptob = scm_new_port_table_entry (channel_tag);
pt = SCM_PTAB_ENTRY (ptob);
@@ -239,7 +240,7 @@ SCM_DEFINE (guile_ssh_make_channel, "make-channel", 1, 0, 0,
if (! ch)
return SCM_BOOL_F;
- return _ssh_channel_to_scm (ch);
+ return _ssh_channel_to_scm (ch, arg1);
}
diff --git a/ssh/channel-type.h b/ssh/channel-type.h
index 7ad959f..cb22098 100644
--- a/ssh/channel-type.h
+++ b/ssh/channel-type.h
@@ -27,6 +27,10 @@ extern scm_t_bits channel_tag;
/* Smob data. */
struct channel_data {
+ /* Reference to the parent session. We need to keep the reference
+ to prevent the session from premature freeing by the GC. */
+ SCM session;
+
ssh_channel ssh_channel;
uint8_t is_stderr;
};
@@ -42,6 +46,6 @@ extern void init_channel_type (void);
/* Helper procedures */
extern struct channel_data *_scm_to_ssh_channel (SCM x);
-extern SCM _ssh_channel_to_scm (ssh_channel ch);
+extern SCM _ssh_channel_to_scm (ssh_channel ch, SCM session);
#endif /* ifndef __CHANNEL_TYPE_H__ */
diff --git a/ssh/message-func.c b/ssh/message-func.c
index ed8d53f..345775f 100644
--- a/ssh/message-func.c
+++ b/ssh/message-func.c
@@ -126,7 +126,7 @@ SCM_DEFINE (guile_ssh_message_channel_request_open_reply_accept,
if (! ch)
return SCM_BOOL_F;
- SCM channel = _ssh_channel_to_scm (ch);
+ SCM channel = _ssh_channel_to_scm (ch, msg_data->session);
SCM_SET_CELL_TYPE (channel, SCM_CELL_TYPE (channel) | SCM_OPN);
return channel;
diff --git a/ssh/message-type.h b/ssh/message-type.h
index 109f8cf..2dbbfd0 100644
--- a/ssh/message-type.h
+++ b/ssh/message-type.h
@@ -27,6 +27,10 @@ extern scm_t_bits message_tag;
/* Smob data. */
struct message_data {
+ /* Reference to the parent session. We need to keep the reference
+ to prevent the session from premature freeing by the GC. */
+ SCM session;
+
ssh_message message;
};
diff --git a/ssh/server-func.c b/ssh/server-func.c
index ca58824..ffa4313 100644
--- a/ssh/server-func.c
+++ b/ssh/server-func.c
@@ -247,6 +247,8 @@ SCM_DEFINE (guile_ssh_server_message_get,
return SCM_BOOL_F;
}
+ message_data->session = session;
+
SCM_NEWSMOB (smob, message_tag, message_data);
return smob;
}