diff options
| -rw-r--r-- | ChangeLog | 21 | ||||
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | ssh/channel-type.c | 5 | ||||
| -rw-r--r-- | ssh/channel-type.h | 6 | ||||
| -rw-r--r-- | ssh/message-func.c | 2 | ||||
| -rw-r--r-- | ssh/message-type.h | 4 | ||||
| -rw-r--r-- | ssh/server-func.c | 2 |
7 files changed, 40 insertions, 4 deletions
@@ -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. @@ -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; } |
