On Mon, Mar 11, 2013 at 01:07:50AM +0100, Holger Hans Peter Freyther wrote:
> Hi,
> 
> I was discussing this crash[1] with Jan at the 29C3 and recently in
> Iceland. On top of that Katarina pointed me to the best practises[2]
> of talloc. In general I disagree with them[3] but they provide a nice
> solution for the SGSN/MSGB ownership issue.

Hi,

so attached is a proof of concept. This has only been compile tested.
In theory the code should now:

1.) Place the msgb in the write_queue when it will be stolen back into
the msgb context (it could be moved into a write queue context)

2.) Delete the msgb in case of error on the way down there..

3.) Catch all and the msgb is still in the local_ctx and we just free it.

Please comment.

        holger
diff --git a/src/write_queue.c b/src/write_queue.c
index cef40f8..3f587dc 100644
--- a/src/write_queue.c
+++ b/src/write_queue.c
@@ -22,6 +22,9 @@
  */
 
 #include <osmocom/core/write_queue.h>
+#include <osmocom/core/talloc.h>
+
+extern void *tall_msgb_ctx;
 
 /*! \addtogroup write_queue
  *  @{
@@ -92,6 +95,9 @@ int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
 //	if (queue->current_length + 1 >= queue->max_length)
 //		LOGP(DMSC, LOGL_ERROR, "The queue is full. Dropping not yet implemented.\n");
 
+	/* take ownership and potentially move it back to the msgb ctx */
+	talloc_steal(tall_msgb_ctx, data);
+
 	++queue->current_length;
 	msgb_enqueue(&queue->msg_queue, data);
 	queue->bfd.when |= BSC_FD_WRITE;
diff --git a/openbsc/src/gprs/gprs_sndcp.c b/openbsc/src/gprs/gprs_sndcp.c
index 853f8db..d3112e7 100644
--- a/openbsc/src/gprs/gprs_sndcp.c
+++ b/openbsc/src/gprs/gprs_sndcp.c
@@ -353,16 +353,24 @@ static int sndcp_send_ud_frag(struct sndcp_frag_state *fs)
 	struct sndcp_comp_hdr *scomph;
 	struct sndcp_udata_hdr *suh;
 	struct msgb *fmsg;
+	void *local_ctx;
 	unsigned int max_payload_len;
 	unsigned int len;
 	uint8_t *data;
 	int rc, more;
 
+	local_ctx = talloc_new(NULL);
+	if (!local_ctx)
+		return -ENOMEM;
+
 	fmsg = msgb_alloc_headroom(fs->sne->lle->params.n201_u+256, 128,
 				   "SNDCP Frag");
 	if (!fmsg)
 		return -ENOMEM;
 
+	/* now steal into the context */
+	talloc_steal(local_ctx, fmsg);
+
 	/* make sure lower layers route the fragment like the original */
 	msgb_tlli(fmsg) = msgb_tlli(fs->msg);
 	msgb_bvci(fmsg) = msgb_bvci(fs->msg);
@@ -418,9 +426,9 @@ static int sndcp_send_ud_frag(struct sndcp_frag_state *fs)
 	sch->more = more;
 
 	rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext);
+	talloc_free(local_ctx);
 	if (rc < 0) {
 		/* abort in case of error, do not advance frag_nr / next_byte */
-		msgb_free(fmsg);
 		return rc;
 	}
 

Reply via email to