From: Matthias Wachs Date: Thu, 24 May 2012 08:43:24 +0000 (+0000) Subject: - fix for 0002371, 0002343: mst freed in callback X-Git-Tag: initial-import-from-subversion-38251~13422 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6743123dcc6b37dabf2759f384a7f6ad08a08bec;p=oweals%2Fgnunet.git - fix for 0002371, 0002343: mst freed in callback --- diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h index c0a0a5cba..73fe8000e 100644 --- a/src/include/gnunet_server_lib.h +++ b/src/include/gnunet_server_lib.h @@ -607,11 +607,15 @@ struct GNUNET_SERVER_MessageStreamTokenizer; * Functions with this signature are called whenever a * complete message is received by the tokenizer. * + * Do not call GNUNET_SERVER_mst_destroy in callback + * * @param cls closure * @param client identification of the client * @param message the actual message + * + * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ -typedef void (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls, void *client, +typedef int (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls, void *client, const struct GNUNET_MessageHeader * message); diff --git a/src/util/Makefile.am b/src/util/Makefile.am index eb0495998..9e670d950 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -195,6 +195,7 @@ check_PROGRAMS = \ test_resolver_api \ test_scheduler \ test_scheduler_delay \ + test_server_mst_interrupt \ test_server \ test_server_disconnect \ test_server_with_client \ @@ -402,6 +403,11 @@ test_scheduler_delay_SOURCES = \ test_scheduler_delay_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_server_mst_interrupt_SOURCES = \ + test_server_mst_interrupt.c +test_server_mst_interrupt_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + test_server_SOURCES = \ test_server.c test_server_LDADD = \ diff --git a/src/util/server.c b/src/util/server.c index 69d64a702..3f1edf3ea 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -1104,8 +1104,10 @@ restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param cls closure (struct GNUNET_SERVER_Handle) * @param client identification of the client (struct GNUNET_SERVER_Client*) * @param message the actual message + * + * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ -static void +static int client_message_tokenizer_callback (void *cls, void *client, const struct GNUNET_MessageHeader *message) { @@ -1120,7 +1122,11 @@ client_message_tokenizer_callback (void *cls, void *client, ret = GNUNET_SERVER_inject (server, sender, message); sender->in_process_client_buffer = GNUNET_NO; if ( (GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now) ) + { GNUNET_SERVER_client_disconnect (sender); + return GNUNET_SYSERR; + } + return GNUNET_OK; } diff --git a/src/util/server_mst.c b/src/util/server_mst.c index 1523de91a..9dd04f0fa 100644 --- a/src/util/server_mst.c +++ b/src/util/server_mst.c @@ -221,7 +221,8 @@ do_align: if (one_shot == GNUNET_YES) one_shot = GNUNET_SYSERR; mst->off += want; - mst->cb (mst->cb_cls, client_identity, hdr); + if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) + return GNUNET_SYSERR; if (mst->off == mst->pos) { /* reset to beginning of buffer, it's free right now! */ @@ -261,7 +262,8 @@ do_align: } if (one_shot == GNUNET_YES) one_shot = GNUNET_SYSERR; - mst->cb (mst->cb_cls, client_identity, hdr); + if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) + return GNUNET_SYSERR; buf += want; size -= want; } diff --git a/src/util/test_server_mst_interrupt.c b/src/util/test_server_mst_interrupt.c new file mode 100644 index 000000000..fd34bd00a --- /dev/null +++ b/src/util/test_server_mst_interrupt.c @@ -0,0 +1,81 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file util/test_server_mst_interrupt.c + * @brief test for interrupt message processing in server_mst.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_protocols.h" +#include "gnunet_client_lib.h" +#include "gnunet_scheduler_lib.h" +#include "gnunet_server_lib.h" +#include "gnunet_time_lib.h" + +static struct GNUNET_SERVER_MessageStreamTokenizer * mst; +static int ret; + +/* Callback destroying mst with data in buffer */ +static int +mst_cb (void *cls, void *client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MST gave me message, destroying\n"); + GNUNET_SERVER_mst_destroy (mst); + return GNUNET_SYSERR; +} + +/** + * Main method + */ +static int +check () +{ + + struct GNUNET_PeerIdentity id; + struct GNUNET_MessageHeader msg[2]; + + /* Prepare */ + memset (&id, sizeof (id), '\0'); + msg[0].size = htons (sizeof (msg)); + msg[0].type = htons (sizeof (GNUNET_MESSAGE_TYPE_DUMMY)); + + mst = GNUNET_SERVER_mst_create(mst_cb, NULL); + + GNUNET_SERVER_mst_receive(mst, &id, (const char *) &msg, 2 * sizeof (msg), GNUNET_NO, GNUNET_NO); + + /* If we reach this line, it did not crash */ + ret = 0; + + return ret; +} + +int +main (int argc, char *argv[]) +{ + ret = 1; + + GNUNET_log_setup ("test_server", "WARNING", NULL); + check (); + + return ret; +} + +/* end of test_server_mst_interrupt.c */