Commit bc86794f authored by Havoc Pennington's avatar Havoc Pennington

2003-03-30 Havoc Pennington <hp@pobox.com>

	* bus/config-parser.c: hacking

	* dbus/dbus-memory.c: don't use DBusList for the list of stuff
	to shut down, since it could cause weirdness with the DBusList
	lock

	* dbus/dbus-list.c (_dbus_list_test): add tests for the
	link-oriented stack routines
	(alloc_link): free the mempool if the first alloc from it fails

	* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue

	* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
	from GLib
	(_dbus_string_skip_white): new

	* doc/config-file.txt (Elements): add <includedir>
parent d361874e
2003-03-30 Havoc Pennington <hp@pobox.com>
* bus/config-parser.c: hacking
* dbus/dbus-memory.c: don't use DBusList for the list of stuff
to shut down, since it could cause weirdness with the DBusList
lock
* dbus/dbus-list.c (_dbus_list_test): add tests for the
link-oriented stack routines
(alloc_link): free the mempool if the first alloc from it fails
* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue
* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
from GLib
(_dbus_string_skip_white): new
* doc/config-file.txt (Elements): add <includedir>
2003-03-28 Havoc Pennington <hp@pobox.com>
* dbus/dbus-string.c (_dbus_string_copy_data_len)
(_dbus_string_copy_data): new functions
2003-03-28 Anders Carlsson <andersca@codefactory.se> 2003-03-28 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-bus.c: (bus_data_free), (dbus_bus_get): * dbus/dbus-bus.c: (bus_data_free), (dbus_bus_get):
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (C) 2003 Red Hat, Inc. * Copyright (C) 2003 Red Hat, Inc.
* *
* Licensed under the Academic Free License version 1.2 * Licensed under the Academic Free License version 1.2
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
...@@ -41,6 +41,27 @@ typedef struct ...@@ -41,6 +41,27 @@ typedef struct
dbus_bool_t failed; dbus_bool_t failed;
} ExpatParseContext; } ExpatParseContext;
static dbus_bool_t
process_content (ExpatParseContext *context)
{
if (context->failed)
return FALSE;
if (_dbus_string_get_length (&context->content) > 0)
{
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return FALSE;
}
_dbus_string_set_length (&context->content, 0);
}
return TRUE;
}
static void static void
expat_StartElementHandler (void *userData, expat_StartElementHandler (void *userData,
const XML_Char *name, const XML_Char *name,
...@@ -50,13 +71,16 @@ expat_StartElementHandler (void *userData, ...@@ -50,13 +71,16 @@ expat_StartElementHandler (void *userData,
int i; int i;
char **names; char **names;
char **values; char **values;
/* Expat seems to suck and can't abort the parse if we /* Expat seems to suck and can't abort the parse if we
* throw an error. Expat 2.0 is supposed to fix this. * throw an error. Expat 2.0 is supposed to fix this.
*/ */
if (context->failed) if (context->failed)
return; return;
if (!process_content (context))
return;
/* "atts" is key, value, key, value, NULL */ /* "atts" is key, value, key, value, NULL */
for (i = 0; atts[i] != NULL; ++i) for (i = 0; atts[i] != NULL; ++i)
; /* nothing */ ; /* nothing */
...@@ -73,17 +97,17 @@ expat_StartElementHandler (void *userData, ...@@ -73,17 +97,17 @@ expat_StartElementHandler (void *userData,
dbus_free (values); dbus_free (values);
return; return;
} }
i = 0; i = 0;
while (atts[i] != NULL) while (atts[i] != NULL)
{ {
_dbus_assert (i % 2 == 0); _dbus_assert (i % 2 == 0);
names [i / 2] = (char*) atts[i]; names [i / 2] = (char*) atts[i];
values[i / 2 + 1] = (char*) atts[i+1]; values[i / 2] = (char*) atts[i+1];
i += 2; i += 2;
} }
if (!bus_config_parser_start_element (context->parser, if (!bus_config_parser_start_element (context->parser,
name, name,
(const char **) names, (const char **) names,
...@@ -105,20 +129,9 @@ expat_EndElementHandler (void *userData, ...@@ -105,20 +129,9 @@ expat_EndElementHandler (void *userData,
const XML_Char *name) const XML_Char *name)
{ {
ExpatParseContext *context = userData; ExpatParseContext *context = userData;
if (context->failed)
return;
if (_dbus_string_get_length (&context->content) > 0) if (!process_content (context))
{ return;
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return;
}
_dbus_string_set_length (&context->content, 0);
}
if (!bus_config_parser_end_element (context->parser, if (!bus_config_parser_end_element (context->parser,
name, name,
...@@ -157,22 +170,22 @@ bus_config_load (const DBusString *file, ...@@ -157,22 +170,22 @@ bus_config_load (const DBusString *file,
const char *filename; const char *filename;
BusConfigParser *parser; BusConfigParser *parser;
ExpatParseContext context; ExpatParseContext context;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
parser = NULL; parser = NULL;
expat = NULL; expat = NULL;
context.error = error; context.error = error;
context.failed = FALSE; context.failed = FALSE;
_dbus_string_get_const_data (file, &filename); _dbus_string_get_const_data (file, &filename);
if (!_dbus_string_init (&context.content, _DBUS_INT_MAX)) if (!_dbus_string_init (&context.content, _DBUS_INT_MAX))
{ {
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL; return NULL;
} }
expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL); expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
if (expat == NULL) if (expat == NULL)
{ {
...@@ -186,6 +199,7 @@ bus_config_load (const DBusString *file, ...@@ -186,6 +199,7 @@ bus_config_load (const DBusString *file,
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed; goto failed;
} }
context.parser = parser;
XML_SetUserData (expat, &context); XML_SetUserData (expat, &context);
XML_SetElementHandler (expat, XML_SetElementHandler (expat,
...@@ -197,28 +211,28 @@ bus_config_load (const DBusString *file, ...@@ -197,28 +211,28 @@ bus_config_load (const DBusString *file,
{ {
DBusString data; DBusString data;
const char *data_str; const char *data_str;
if (!_dbus_string_init (&data, _DBUS_INT_MAX)) if (!_dbus_string_init (&data, _DBUS_INT_MAX))
{ {
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed; goto failed;
} }
if (!_dbus_file_get_contents (&data, file, error)) if (!_dbus_file_get_contents (&data, file, error))
{ {
_dbus_string_free (&data); _dbus_string_free (&data);
goto failed; goto failed;
} }
_dbus_string_get_const_data (&data, &data_str); _dbus_string_get_const_data (&data, &data_str);
if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE)) if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
{ {
if (context.error != NULL && if (context.error != NULL &&
!dbus_error_is_set (context.error)) !dbus_error_is_set (context.error))
{ {
enum XML_Error e; enum XML_Error e;
e = XML_GetErrorCode (expat); e = XML_GetErrorCode (expat);
if (e == XML_ERROR_NO_MEMORY) if (e == XML_ERROR_NO_MEMORY)
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
...@@ -230,7 +244,7 @@ bus_config_load (const DBusString *file, ...@@ -230,7 +244,7 @@ bus_config_load (const DBusString *file,
XML_GetCurrentColumnNumber (expat), XML_GetCurrentColumnNumber (expat),
XML_ErrorString (e)); XML_ErrorString (e));
} }
_dbus_string_free (&data); _dbus_string_free (&data);
goto failed; goto failed;
} }
...@@ -240,7 +254,7 @@ bus_config_load (const DBusString *file, ...@@ -240,7 +254,7 @@ bus_config_load (const DBusString *file,
if (context.failed) if (context.failed)
goto failed; goto failed;
} }
if (!bus_config_parser_finished (parser, error)) if (!bus_config_parser_finished (parser, error))
goto failed; goto failed;
...@@ -249,10 +263,10 @@ bus_config_load (const DBusString *file, ...@@ -249,10 +263,10 @@ bus_config_load (const DBusString *file,
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
return parser; return parser;
failed: failed:
_DBUS_ASSERT_ERROR_IS_SET (error); _DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_string_free (&context.content); _dbus_string_free (&context.content);
if (expat) if (expat)
XML_ParserFree (expat); XML_ParserFree (expat);
......
This diff is collapsed.
...@@ -69,8 +69,8 @@ main (int argc, char **argv) ...@@ -69,8 +69,8 @@ main (int argc, char **argv)
printf ("%s: Running config file parser test\n", argv[0]); printf ("%s: Running config file parser test\n", argv[0]);
if (!bus_config_parser_test (&test_data_dir)) if (!bus_config_parser_test (&test_data_dir))
die ("parser"); die ("parser");
check_memleaks (argv[0]); check_memleaks (argv[0]);
printf ("%s: Running policy test\n", argv[0]); printf ("%s: Running policy test\n", argv[0]);
if (!bus_policy_test (&test_data_dir)) if (!bus_policy_test (&test_data_dir))
......
...@@ -345,7 +345,7 @@ _dbus_test_oom_handling (const char *description, ...@@ -345,7 +345,7 @@ _dbus_test_oom_handling (const char *description,
if (!(* func) (data)) if (!(* func) (data))
return FALSE; return FALSE;
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
_dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n", _dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
......
...@@ -212,7 +212,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (atomic); ...@@ -212,7 +212,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (atomic);
_DBUS_DECLARE_GLOBAL_LOCK (message_handler); _DBUS_DECLARE_GLOBAL_LOCK (message_handler);
_DBUS_DECLARE_GLOBAL_LOCK (user_info); _DBUS_DECLARE_GLOBAL_LOCK (user_info);
_DBUS_DECLARE_GLOBAL_LOCK (bus); _DBUS_DECLARE_GLOBAL_LOCK (bus);
#define _DBUS_N_GLOBAL_LOCKS (7) _DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
#define _DBUS_N_GLOBAL_LOCKS (8)
DBUS_END_DECLS; DBUS_END_DECLS;
......
...@@ -57,8 +57,8 @@ alloc_link (void *data) ...@@ -57,8 +57,8 @@ alloc_link (void *data)
if (!_DBUS_LOCK (list)) if (!_DBUS_LOCK (list))
return NULL; return NULL;
if (!list_pool) if (list_pool == NULL)
{ {
list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE); list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
...@@ -67,9 +67,21 @@ alloc_link (void *data) ...@@ -67,9 +67,21 @@ alloc_link (void *data)
_DBUS_UNLOCK (list); _DBUS_UNLOCK (list);
return NULL; return NULL;
} }
link = _dbus_mem_pool_alloc (list_pool);
if (link == NULL)
{
_dbus_mem_pool_free (list_pool);
list_pool = NULL;
_DBUS_UNLOCK (list);
return NULL;
}
} }
else
link = _dbus_mem_pool_alloc (list_pool); {
link = _dbus_mem_pool_alloc (list_pool);
}
if (link) if (link)
link->data = data; link->data = data;
...@@ -80,13 +92,14 @@ alloc_link (void *data) ...@@ -80,13 +92,14 @@ alloc_link (void *data)
static void static void
free_link (DBusList *link) free_link (DBusList *link)
{ {
_DBUS_LOCK (list); _DBUS_LOCK (list);
if (_dbus_mem_pool_dealloc (list_pool, link)) if (_dbus_mem_pool_dealloc (list_pool, link))
{ {
_dbus_mem_pool_free (list_pool); _dbus_mem_pool_free (list_pool);
list_pool = NULL; list_pool = NULL;
} }
_DBUS_UNLOCK (list); _DBUS_UNLOCK (list);
} }
...@@ -607,6 +620,27 @@ _dbus_list_pop_last (DBusList **list) ...@@ -607,6 +620,27 @@ _dbus_list_pop_last (DBusList **list)
return data; return data;
} }
/**
* Removes the last link in the list and returns it. This is a
* constant-time operation.
*
* @param list address of the list head.
* @returns the last link in the list, or #NULL for an empty list.
*/
DBusList*
_dbus_list_pop_last_link (DBusList **list)
{
DBusList *link;
link = _dbus_list_get_last_link (list);
if (link == NULL)
return NULL;
_dbus_list_unlink (list, link);
return link;
}
/** /**
* Copies a list. This is a linear-time operation. If there isn't * Copies a list. This is a linear-time operation. If there isn't
* enough memory to copy the entire list, the destination list will be * enough memory to copy the entire list, the destination list will be
...@@ -952,6 +986,58 @@ _dbus_list_test (void) ...@@ -952,6 +986,58 @@ _dbus_list_test (void)
_dbus_assert (list1 == NULL); _dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL); _dbus_assert (list2 == NULL);
/* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
i = 0;
while (i < 10)
{
_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
++i;
}
--i;
while (i >= 0)
{
DBusList *got_link1;
DBusList *got_link2;
DBusList *link1;
DBusList *link2;
void *data1;
void *data2;
got_link1 = _dbus_list_get_last_link (&list1);
got_link2 = _dbus_list_get_first_link (&list2);
link1 = _dbus_list_pop_last_link (&list1);
link2 = _dbus_list_pop_first_link (&list2);
_dbus_assert (got_link1 == link1);
_dbus_assert (got_link2 == link2);
data1 = link1->data;
data2 = link2->data;
_dbus_list_free_link (link1);
_dbus_list_free_link (link2);
_dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
_dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
verify_list (&list1);
verify_list (&list2);
_dbus_assert (is_ascending_sequence (&list1));
_dbus_assert (is_descending_sequence (&list2));
--i;
}
_dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL);
/* Test iteration */ /* Test iteration */
i = 0; i = 0;
......
/* -*- mode: C; c-file-style: "gnu" -*- */ /* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-list.h Generic linked list utility (internal to D-BUS implementation) /* dbus-list.h Generic linked list utility (internal to D-BUS implementation)
* *
* Copyright (C) 2002 Red Hat, Inc. * Copyright (C) 2002, 2003 Red Hat, Inc.
* *
* Licensed under the Academic Free License version 1.2 * Licensed under the Academic Free License version 1.2
* *
...@@ -63,6 +63,7 @@ void* _dbus_list_get_first (DBusList **list); ...@@ -63,6 +63,7 @@ void* _dbus_list_get_first (DBusList **list);
void* _dbus_list_pop_first (DBusList **list); void* _dbus_list_pop_first (DBusList **list);
void* _dbus_list_pop_last (DBusList **list); void* _dbus_list_pop_last (DBusList **list);
DBusList* _dbus_list_pop_first_link (DBusList **list); DBusList* _dbus_list_pop_first_link (DBusList **list);
DBusList* _dbus_list_pop_last_link (DBusList **list);
dbus_bool_t _dbus_list_copy (DBusList **list, dbus_bool_t _dbus_list_copy (DBusList **list,
DBusList **dest); DBusList **dest);
int _dbus_list_get_length (DBusList **list); int _dbus_list_get_length (DBusList **list);
......
...@@ -633,13 +633,17 @@ dbus_free_string_array (char **str_array) ...@@ -633,13 +633,17 @@ dbus_free_string_array (char **str_array)
*/ */
int _dbus_current_generation = 1; int _dbus_current_generation = 1;
static DBusList *registered_globals = NULL; typedef struct ShutdownClosure ShutdownClosure;
typedef struct struct ShutdownClosure
{ {
ShutdownClosure *next;
DBusShutdownFunction func; DBusShutdownFunction func;
void *data; void *data;
} ShutdownClosure; };
_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
static ShutdownClosure *registered_globals = NULL;
/** /**
* The D-BUS library keeps some internal global variables, for example * The D-BUS library keeps some internal global variables, for example
...@@ -656,22 +660,18 @@ typedef struct ...@@ -656,22 +660,18 @@ typedef struct
void void
dbus_shutdown (void) dbus_shutdown (void)
{ {
DBusList *link; while (registered_globals != NULL)
link = _dbus_list_get_first_link (&registered_globals);
while (link != NULL)
{ {
ShutdownClosure *c = link->data; ShutdownClosure *c;
c = registered_globals;
registered_globals = c->next;
(* c->func) (c->data); (* c->func) (c->data);
dbus_free (c);
link = _dbus_list_get_next_link (&registered_globals, link); dbus_free (c);
} }
_dbus_list_clear (&registered_globals);
_dbus_current_generation += 1; _dbus_current_generation += 1;
} }
...@@ -693,20 +693,17 @@ _dbus_register_shutdown_func (DBusShutdownFunction func, ...@@ -693,20 +693,17 @@ _dbus_register_shutdown_func (DBusShutdownFunction func,
if (c == NULL) if (c == NULL)
return FALSE; return FALSE;
c->func = func; c->func = func;
c->data = data; c->data = data;
/* We prepend, then shutdown the list in order, so _DBUS_LOCK (shutdown_funcs);
* we shutdown last-registered stuff first which
* is right. c->next = registered_globals;
*/ registered_globals = c;
if (!_dbus_list_prepend (&registered_globals, c))
{
dbus_free (c);
return FALSE;
}
_DBUS_UNLOCK (shutdown_funcs);
return TRUE; return TRUE;
} }
......
...@@ -84,7 +84,8 @@ struct DBusMemBlock ...@@ -84,7 +84,8 @@ struct DBusMemBlock
* when we free the mem pool. * when we free the mem pool.
*/ */
int used_so_far; /**< bytes of this block already allocated as elements. */ /* this is a long so that "elements" is aligned */
long used_so_far; /**< bytes of this block already allocated as elements. */
unsigned char elements[ELEMENT_PADDING]; /**< the block data, actually allocated to required size */ unsigned char elements[ELEMENT_PADDING]; /**< the block data, actually allocated to required size */
}; };
...@@ -254,7 +255,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) ...@@ -254,7 +255,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
memset (element, '\0', pool->element_size); memset (element, '\0', pool->element_size);
pool->allocated_elements += 1; pool->allocated_elements += 1;
return element; return element;
} }
else else
...@@ -311,11 +312,11 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) ...@@ -311,11 +312,11 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
} }
element = &pool->blocks->elements[pool->blocks->used_so_far]; element = &pool->blocks->elements[pool->blocks->used_so_far];
pool->blocks->used_so_far += pool->element_size; pool->blocks->used_so_far += pool->element_size;
pool->allocated_elements += 1; pool->allocated_elements += 1;
return element; return element;
} }
} }
......
...@@ -633,7 +633,74 @@ _dbus_string_steal_data_len (DBusString *str, ...@@ -633,7 +633,74 @@ _dbus_string_steal_data_len (DBusString *str,
return FALSE; return FALSE;
} }
_dbus_warn ("Broken code in _dbus_string_steal_data_len(), FIXME\n"); _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
if (!_dbus_string_steal_data (&dest, data_return))
{
_dbus_string_free (&dest);
return FALSE;
}
_dbus_string_free (&dest);
return TRUE;
}
/**
* Copies the data from the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @returns #TRUE on success, #FALSE on no memory
*/
dbus_bool_t
_dbus_string_copy_data (const DBusString *str,
char **data_return)
{
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
*data_return = dbus_malloc (real->len + 1);
if (*data_return == NULL)
return FALSE;
memcpy (*data_return, real->str, real->len + 1);
return TRUE;
}
/**
* Copies a segment of the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @param start start index
* @param len length to copy