diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 1f4e083ce..2108a1efa 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -861,20 +861,33 @@ static void table_put(struct rtpengine_table *t) { +/* must be called lock-free */ static inline void free_packet(struct re_stream_packet *packet) { if (packet->skbuf) kfree_skb(packet->skbuf); kfree(packet); } -/* caller is responsible for locking */ +/* must be called lock-free */ static void clear_stream_packets(struct re_stream *stream) { struct re_stream_packet *packet; + unsigned long flags; + LIST_HEAD(delete_list); + + spin_lock_irqsave(&stream->packet_list_lock, flags); while (!list_empty(&stream->packet_list)) { DBG("clearing packet from queue\n"); packet = list_first_entry(&stream->packet_list, struct re_stream_packet, list_entry); list_del(&packet->list_entry); + list_add(&packet->list_entry, &delete_list); + } + + spin_unlock_irqrestore(&stream->packet_list_lock, flags); + + while (!list_empty(&delete_list)) { + packet = list_first_entry(&delete_list, struct re_stream_packet, list_entry); + list_del(&packet->list_entry); free_packet(packet); } } @@ -2673,10 +2686,11 @@ static void del_stream(struct re_stream *stream, struct rtpengine_table *table) } stream->eof = 1; - clear_stream_packets(stream); spin_unlock_irqrestore(&stream->packet_list_lock, flags); + clear_stream_packets(stream); + DBG("stream is finished (EOF), waking up threads\n"); wake_up_interruptible(&stream->wq); /* sleeping readers will now close files */