meta: fix refactor to a better layout
[scm/bb/meta-tizen.git] / meta-tizen-adaptation / meta / recipes-core / dbus / files / 0009-Make-taking-a-global-lock-automatically-initialize-l.patch
1 From: Simon McVittie <simon.mcvittie@collabora.co.uk>
2 Date: Tue, 16 Apr 2013 16:28:44 +0100
3 Subject: Make taking a global lock automatically initialize locking if needed
4
5 This lets them be thread-safe by default, at the cost that they can
6 now fail.
7
8 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
9 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
10 Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
11 Reviewed-by: Anas Nashif <anas.nashif@intel.com>
12 Applied-upstream: 1.7.6, commit:2b3272c75ae48c93911bd6f656965cf77d6de3e8
13 Bug-Tizen: TZPC-1971
14 Change-Id: I7e547e5776d37051ec8b6eccc2c8bd34b8d1996b
15 ---
16  bus/stats.c                        |  4 +--
17  dbus/dbus-bus.c                    | 52 ++++++++++++++++++++++++++++++--------
18  dbus/dbus-connection.c             | 50 ++++++++++++++++++++++++++----------
19  dbus/dbus-dataslot.c               | 19 ++++++++++----
20  dbus/dbus-internals.c              |  8 ++++--
21  dbus/dbus-internals.h              |  4 +--
22  dbus/dbus-list.c                   | 17 ++++++++++---
23  dbus/dbus-memory.c                 |  4 ++-
24  dbus/dbus-message.c                | 19 +++++++++++---
25  dbus/dbus-threads.c                | 28 +++++++++++++-------
26  dbus/dbus-userdb-util.c            | 20 ++++++++++++---
27  dbus/dbus-userdb.c                 | 43 +++++++++++++++++++++++--------
28  dbus/dbus-userdb.h                 |  2 +-
29  test/name-test/test-threads-init.c | 14 ++++++----
30  14 files changed, 213 insertions(+), 71 deletions(-)
31
32 diff --git a/bus/stats.c b/bus/stats.c
33 index 28fd49b..4553191 100644
34 --- a/bus/stats.c
35 +++ b/bus/stats.c
36 @@ -203,8 +203,8 @@ bus_stats_handle_get_stats (DBusConnection *connection,
37    if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
38      goto oom;
39  
40 -  _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
41 -  if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
42 +  if (!_dbus_list_get_stats (&in_use, &in_free_list, &allocated) ||
43 +      !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
44        !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
45                         in_free_list) ||
46        !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
47 diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
48 index 7a31cbd..3aa5c09 100644
49 --- a/dbus/dbus-bus.c
50 +++ b/dbus/dbus-bus.c
51 @@ -317,7 +317,11 @@ bus_data_free (void *data)
52    if (bd->is_well_known)
53      {
54        int i;
55 -      _DBUS_LOCK (bus);
56 +
57 +      if (!_DBUS_LOCK (bus))
58 +        _dbus_assert_not_reached ("global locks should have been initialized "
59 +            "when we attached bus data");
60 +
61        /* We may be stored in more than one slot */
62        /* This should now be impossible - these slots are supposed to
63         * be cleared on disconnect, so should not need to be cleared on
64 @@ -388,8 +392,13 @@ void
65  _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection)
66  {
67    int i;
68 -  
69 -  _DBUS_LOCK (bus);
70 +
71 +  if (!_DBUS_LOCK (bus))
72 +    {
73 +      /* If it was in bus_connections, we would have initialized global locks
74 +       * when we added it. So, it can't be. */
75 +      return;
76 +    }
77  
78    /* We are expecting to have the connection saved in only one of these
79     * slots, but someone could in a pathological case set system and session
80 @@ -423,7 +432,12 @@ internal_bus_get (DBusBusType  type,
81  
82    connection = NULL;
83  
84 -  _DBUS_LOCK (bus);
85 +  if (!_DBUS_LOCK (bus))
86 +    {
87 +      _DBUS_SET_OOM (error);
88 +      /* do not "goto out", that would try to unlock */
89 +      return NULL;
90 +    }
91  
92    if (!init_connections_unlocked ())
93      {
94 @@ -493,8 +507,10 @@ internal_bus_get (DBusBusType  type,
95     */
96    dbus_connection_set_exit_on_disconnect (connection,
97                                            TRUE);
98
99 -  _DBUS_LOCK (bus_datas);
100 +
101 +  if (!_DBUS_LOCK (bus_datas))
102 +    _dbus_assert_not_reached ("global locks were initialized already");
103 +
104    bd = ensure_bus_data (connection);
105    _dbus_assert (bd != NULL); /* it should have been created on
106                                  register, so OOM not possible */
107 @@ -647,7 +663,12 @@ dbus_bus_register (DBusConnection *connection,
108    message = NULL;
109    reply = NULL;
110  
111 -  _DBUS_LOCK (bus_datas);
112 +  if (!_DBUS_LOCK (bus_datas))
113 +    {
114 +      _DBUS_SET_OOM (error);
115 +      /* do not "goto out", that would try to unlock */
116 +      return FALSE;
117 +    }
118  
119    bd = ensure_bus_data (connection);
120    if (bd == NULL)
121 @@ -756,8 +777,12 @@ dbus_bus_set_unique_name (DBusConnection *connection,
122    _dbus_return_val_if_fail (connection != NULL, FALSE);
123    _dbus_return_val_if_fail (unique_name != NULL, FALSE);
124  
125 -  _DBUS_LOCK (bus_datas);
126 -  
127 +  if (!_DBUS_LOCK (bus_datas))
128 +    {
129 +      /* do not "goto out", that would try to unlock */
130 +      return FALSE;
131 +    }
132 +
133    bd = ensure_bus_data (connection);
134    if (bd == NULL)
135      goto out;
136 @@ -799,8 +824,13 @@ dbus_bus_get_unique_name (DBusConnection *connection)
137  
138    _dbus_return_val_if_fail (connection != NULL, NULL);
139  
140 -  _DBUS_LOCK (bus_datas);
141 -  
142 +  if (!_DBUS_LOCK (bus_datas))
143 +    {
144 +      /* We'd have initialized locks when we gave it its unique name, if it
145 +       * had one. Don't "goto out", that would try to unlock. */
146 +      return NULL;
147 +    }
148 +
149    bd = ensure_bus_data (connection);
150    if (bd == NULL)
151      goto out;
152 diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
153 index 03ee066..87cfeb0 100644
154 --- a/dbus/dbus-connection.c
155 +++ b/dbus/dbus-connection.c
156 @@ -1555,9 +1555,14 @@ static void
157  shared_connections_shutdown (void *data)
158  {
159    int n_entries;
160 -  
161 -  _DBUS_LOCK (shared_connections);
162 -  
163 +
164 +  if (!_DBUS_LOCK (shared_connections))
165 +    {
166 +      /* We'd have initialized locks before adding anything, so there
167 +       * can't be anything there. */
168 +      return;
169 +    }
170 +
171    /* This is a little bit unpleasant... better ideas? */
172    while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
173      {
174 @@ -1571,7 +1576,8 @@ shared_connections_shutdown (void *data)
175  
176        _DBUS_UNLOCK (shared_connections);
177        close_connection_on_shutdown (connection);
178 -      _DBUS_LOCK (shared_connections);
179 +      if (!_DBUS_LOCK (shared_connections))
180 +        _dbus_assert_not_reached ("global locks were already initialized");
181  
182        /* The connection should now be dead and not in our hash ... */
183        _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
184 @@ -1590,7 +1596,8 @@ shared_connections_shutdown (void *data)
185          {
186            _DBUS_UNLOCK (shared_connections);
187            close_connection_on_shutdown (connection);
188 -          _DBUS_LOCK (shared_connections);
189 +          if (!_DBUS_LOCK (shared_connections))
190 +            _dbus_assert_not_reached ("global locks were already initialized");
191            connection = _dbus_list_pop_first (&shared_connections_no_guid);
192          }
193      }
194 @@ -1607,8 +1614,13 @@ connection_lookup_shared (DBusAddressEntry  *entry,
195    _dbus_verbose ("checking for existing connection\n");
196    
197    *result = NULL;
198 -  
199 -  _DBUS_LOCK (shared_connections);
200 +
201 +  if (!_DBUS_LOCK (shared_connections))
202 +    {
203 +      /* If it was shared, we'd have initialized global locks when we put
204 +       * it in shared_connections. */
205 +      return FALSE;
206 +    }
207  
208    if (shared_connections == NULL)
209      {
210 @@ -1706,7 +1718,8 @@ connection_record_shared_unlocked (DBusConnection *connection,
211  
212    if (guid == NULL)
213      {
214 -      _DBUS_LOCK (shared_connections);
215 +      if (!_DBUS_LOCK (shared_connections))
216 +        return FALSE;
217  
218        if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
219          {
220 @@ -1733,8 +1746,14 @@ connection_record_shared_unlocked (DBusConnection *connection,
221        dbus_free (guid_key);
222        return FALSE;
223      }
224 -  
225 -  _DBUS_LOCK (shared_connections);
226 +
227 +  if (!_DBUS_LOCK (shared_connections))
228 +    {
229 +      dbus_free (guid_in_connection);
230 +      dbus_free (guid_key);
231 +      return FALSE;
232 +    }
233 +
234    _dbus_assert (shared_connections != NULL);
235    
236    if (!_dbus_hash_table_insert_string (shared_connections,
237 @@ -1765,9 +1784,14 @@ connection_forget_shared_unlocked (DBusConnection *connection)
238  
239    if (!connection->shareable)
240      return;
241 -  
242 -  _DBUS_LOCK (shared_connections);
243 -      
244 +
245 +  if (!_DBUS_LOCK (shared_connections))
246 +    {
247 +      /* If it was shared, we'd have initialized global locks when we put
248 +       * it in the table; so it can't be there. */
249 +      return;
250 +    }
251 +
252    if (connection->server_guid != NULL)
253      {
254        _dbus_verbose ("dropping connection to %s out of the shared table\n",
255 diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c
256 index b3c8090..412e7f4 100644
257 --- a/dbus/dbus-dataslot.c
258 +++ b/dbus/dbus-dataslot.c
259 @@ -71,7 +71,8 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
260  {
261    dbus_int32_t slot;
262  
263 -  _dbus_lock (allocator->lock);
264 +  if (!_dbus_lock (allocator->lock))
265 +    return FALSE;
266  
267    if (*slot_id_p >= 0)
268      {
269 @@ -153,8 +154,10 @@ void
270  _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
271                                  dbus_int32_t          *slot_id_p)
272  {
273 -  _dbus_lock (allocator->lock);
274 -  
275 +  if (!_dbus_lock (allocator->lock))
276 +    _dbus_assert_not_reached ("we should have initialized global locks "
277 +        "before we allocated this slot");
278 +
279    _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
280    _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
281    _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);
282 @@ -228,7 +231,10 @@ _dbus_data_slot_list_set  (DBusDataSlotAllocator *allocator,
283     * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
284     * are disabled, since then the asserts are empty.
285     */
286 -  _dbus_lock (allocator->lock);
287 +  if (!_dbus_lock (allocator->lock))
288 +    _dbus_assert_not_reached ("we should have initialized global locks "
289 +        "before we allocated this slot");
290 +
291    _dbus_assert (slot < allocator->n_allocated_slots);
292    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
293    _dbus_unlock (allocator->lock);
294 @@ -285,7 +291,10 @@ _dbus_data_slot_list_get  (DBusDataSlotAllocator *allocator,
295     * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
296     * are disabled, since then the asserts are empty.
297     */
298 -  _dbus_lock (allocator->lock);
299 +  if (!_dbus_lock (allocator->lock))
300 +    _dbus_assert_not_reached ("we should have initialized global locks "
301 +        "before we allocated this slot");
302 +
303    _dbus_assert (slot >= 0);
304    _dbus_assert (slot < allocator->n_allocated_slots);
305    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
306 diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
307 index 1a36734..63559be 100644
308 --- a/dbus/dbus-internals.c
309 +++ b/dbus/dbus-internals.c
310 @@ -165,7 +165,9 @@
311  /**
312   * @def _DBUS_LOCK
313   *
314 - * Locks a global lock
315 + * Locks a global lock, initializing it first if necessary.
316 + *
317 + * @returns #FALSE if not enough memory
318   */
319  
320  /**
321 @@ -849,7 +851,9 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
322  {
323    dbus_bool_t ok;
324    
325 -  _DBUS_LOCK (machine_uuid);
326 +  if (!_DBUS_LOCK (machine_uuid))
327 +    return FALSE;
328 +
329    if (machine_uuid_initialized_generation != _dbus_current_generation)
330      {
331        DBusError error = DBUS_ERROR_INIT;
332 diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
333 index 22ad297..edde80b 100644
334 --- a/dbus/dbus-internals.h
335 +++ b/dbus/dbus-internals.h
336 @@ -327,8 +327,8 @@ typedef enum
337    _DBUS_N_GLOBAL_LOCKS
338  } DBusGlobalLock;
339  
340 -void _dbus_lock   (DBusGlobalLock lock);
341 -void _dbus_unlock (DBusGlobalLock lock);
342 +dbus_bool_t _dbus_lock   (DBusGlobalLock lock) _DBUS_GNUC_WARN_UNUSED_RESULT;
343 +void        _dbus_unlock (DBusGlobalLock lock);
344  
345  #define _DBUS_LOCK_NAME(name)           _DBUS_LOCK_##name
346  #define _DBUS_LOCK(name)                _dbus_lock   (_DBUS_LOCK_##name)
347 diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
348 index e5a4940..525e067 100644
349 --- a/dbus/dbus-list.c
350 +++ b/dbus/dbus-list.c
351 @@ -56,7 +56,8 @@ alloc_link (void *data)
352  {
353    DBusList *link;
354  
355 -  _DBUS_LOCK (list);
356 +  if (!_DBUS_LOCK (list))
357 +    return FALSE;
358  
359    if (list_pool == NULL)
360      {      
361 @@ -93,7 +94,10 @@ alloc_link (void *data)
362  static void
363  free_link (DBusList *link)
364  {  
365 -  _DBUS_LOCK (list);
366 +  if (!_DBUS_LOCK (list))
367 +    _dbus_assert_not_reached ("we should have initialized global locks "
368 +        "before we allocated a linked-list link");
369 +
370    if (_dbus_mem_pool_dealloc (list_pool, link))
371      {
372        _dbus_mem_pool_free (list_pool);
373 @@ -152,7 +156,14 @@ _dbus_list_get_stats     (dbus_uint32_t *in_use_p,
374                            dbus_uint32_t *in_free_list_p,
375                            dbus_uint32_t *allocated_p)
376  {
377 -  _DBUS_LOCK (list);
378 +  if (!_DBUS_LOCK (list))
379 +    {
380 +      *in_use_p = 0;
381 +      *in_free_list_p = 0;
382 +      *allocated_p = 0;
383 +      return;
384 +    }
385 +
386    _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
387    _DBUS_UNLOCK (list);
388  }
389 diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
390 index a13b951..6cf0449 100644
391 --- a/dbus/dbus-memory.c
392 +++ b/dbus/dbus-memory.c
393 @@ -812,7 +812,9 @@ _dbus_register_shutdown_func (DBusShutdownFunction  func,
394  {
395    dbus_bool_t ok;
396  
397 -  _DBUS_LOCK (shutdown_funcs);
398 +  if (!_DBUS_LOCK (shutdown_funcs))
399 +    return FALSE;
400 +
401    ok = _dbus_register_shutdown_func_unlocked (func, data);
402    _DBUS_UNLOCK (shutdown_funcs);
403    return ok;
404 diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
405 index 2814569..275c425 100644
406 --- a/dbus/dbus-message.c
407 +++ b/dbus/dbus-message.c
408 @@ -516,7 +516,9 @@ dbus_message_cache_shutdown (void *data)
409  {
410    int i;
411  
412 -  _DBUS_LOCK (message_cache);
413 +  if (!_DBUS_LOCK (message_cache))
414 +    _dbus_assert_not_reached ("we would have initialized global locks "
415 +        "before registering a shutdown function");
416  
417    i = 0;
418    while (i < MAX_MESSAGE_CACHE_SIZE)
419 @@ -548,7 +550,12 @@ dbus_message_get_cached (void)
420  
421    message = NULL;
422  
423 -  _DBUS_LOCK (message_cache);
424 +  if (!_DBUS_LOCK (message_cache))
425 +    {
426 +      /* we'd have initialized global locks before caching anything,
427 +       * so there can't be anything in the cache */
428 +      return NULL;
429 +    }
430  
431    _dbus_assert (message_cache_count >= 0);
432  
433 @@ -660,7 +667,13 @@ dbus_message_cache_or_finalize (DBusMessage *message)
434  
435    was_cached = FALSE;
436  
437 -  _DBUS_LOCK (message_cache);
438 +  if (!_DBUS_LOCK (message_cache))
439 +    {
440 +      /* The only way to get a non-null message goes through
441 +       * dbus_message_get_cached() which takes the lock. */
442 +      _dbus_assert_not_reached ("we would have initialized global locks "
443 +          "the first time we constructed a message");
444 +    }
445  
446    if (!message_cache_shutdown_registered)
447      {
448 diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
449 index 297a7e4..2c2a816 100644
450 --- a/dbus/dbus-threads.c
451 +++ b/dbus/dbus-threads.c
452 @@ -366,10 +366,12 @@ shutdown_uninitialized_locks (void *data)
453    _dbus_list_clear (&uninitialized_condvar_list);
454  }
455  
456 +/* init_global_locks() must be called first. */
457  static dbus_bool_t
458  init_uninitialized_locks (void)
459  {
460    DBusList *link;
461 +  dbus_bool_t ok;
462  
463    _dbus_assert (thread_init_generation != _dbus_current_generation);
464  
465 @@ -422,8 +424,12 @@ init_uninitialized_locks (void)
466    _dbus_list_clear (&uninitialized_cmutex_list);
467    _dbus_list_clear (&uninitialized_condvar_list);
468  
469 -  if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
470 -                                     NULL))
471 +  /* This assumes that init_global_locks() has already been called. */
472 +  _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
473 +  ok = _dbus_register_shutdown_func_unlocked (shutdown_uninitialized_locks, NULL);
474 +  _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
475 +
476 +  if (!ok)
477      goto fail_condvar;
478  
479    return TRUE;
480 @@ -494,9 +500,9 @@ init_global_locks (void)
481          goto failed;
482      }
483  
484 -  _dbus_lock (_DBUS_LOCK_NAME (shutdown_funcs));
485 +  _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
486    ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
487 -  _dbus_unlock (_DBUS_LOCK_NAME (shutdown_funcs));
488 +  _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
489  
490    if (!ok)
491      goto failed;
492 @@ -513,14 +519,18 @@ init_global_locks (void)
493    return FALSE;
494  }
495  
496 -void
497 +dbus_bool_t
498  _dbus_lock (DBusGlobalLock lock)
499  {
500    _dbus_assert (lock >= 0);
501    _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
502  
503 -  if (thread_init_generation == _dbus_current_generation)
504 -    _dbus_platform_rmutex_lock (global_locks[lock]);
505 +  if (thread_init_generation != _dbus_current_generation &&
506 +      !dbus_threads_init_default ())
507 +    return FALSE;
508 +
509 +  _dbus_platform_rmutex_lock (global_locks[lock]);
510 +  return TRUE;
511  }
512  
513  void
514 @@ -529,8 +539,7 @@ _dbus_unlock (DBusGlobalLock lock)
515    _dbus_assert (lock >= 0);
516    _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
517  
518 -  if (thread_init_generation == _dbus_current_generation)
519 -    _dbus_platform_rmutex_unlock (global_locks[lock]);
520 +  _dbus_platform_rmutex_unlock (global_locks[lock]);
521  }
522  
523  /** @} */ /* end of internals */
524 @@ -576,6 +585,7 @@ dbus_threads_init (const DBusThreadFunctions *functions)
525      }
526  
527    if (!_dbus_threads_init_platform_specific() ||
528 +      /* init_global_locks() must be called before init_uninitialized_locks. */
529        !init_global_locks () ||
530        !init_uninitialized_locks ())
531      {
532 diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
533 index 16bf229..a8cc3d1 100644
534 --- a/dbus/dbus-userdb-util.c
535 +++ b/dbus/dbus-userdb-util.c
536 @@ -103,7 +103,11 @@ _dbus_is_console_user (dbus_uid_t uid,
537  
538  #endif /* HAVE_CONSOLE_OWNER_FILE */
539  
540 -  _dbus_user_database_lock_system ();
541 +  if (!_dbus_user_database_lock_system ())
542 +    {
543 +      _DBUS_SET_OOM (error);
544 +      return FALSE;
545 +    }
546  
547    db = _dbus_user_database_get_system ();
548    if (db == NULL)
549 @@ -157,7 +161,10 @@ _dbus_get_group_id (const DBusString  *groupname,
550  {
551    DBusUserDatabase *db;
552    const DBusGroupInfo *info;
553 -  _dbus_user_database_lock_system ();
554 +
555 +  /* FIXME: this can't distinguish ENOMEM from other errors */
556 +  if (!_dbus_user_database_lock_system ())
557 +    return FALSE;
558  
559    db = _dbus_user_database_get_system ();
560    if (db == NULL)
561 @@ -194,7 +201,10 @@ _dbus_get_user_id_and_primary_group (const DBusString  *username,
562  {
563    DBusUserDatabase *db;
564    const DBusUserInfo *info;
565 -  _dbus_user_database_lock_system ();
566 +
567 +  /* FIXME: this can't distinguish ENOMEM from other errors */
568 +  if (!_dbus_user_database_lock_system ())
569 +    return FALSE;
570  
571    db = _dbus_user_database_get_system ();
572    if (db == NULL)
573 @@ -387,7 +397,9 @@ _dbus_groups_from_uid (dbus_uid_t         uid,
574    *group_ids = NULL;
575    *n_group_ids = 0;
576  
577 -  _dbus_user_database_lock_system ();
578 +  /* FIXME: this can't distinguish ENOMEM from other errors */
579 +  if (!_dbus_user_database_lock_system ())
580 +    return FALSE;
581  
582    db = _dbus_user_database_get_system ();
583    if (db == NULL)
584 diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c
585 index 4e8b39a..73f8fce 100644
586 --- a/dbus/dbus-userdb.c
587 +++ b/dbus/dbus-userdb.c
588 @@ -306,11 +306,18 @@ init_system_db (void)
589  /**
590   * Locks global system user database.
591   */
592 -void
593 +dbus_bool_t
594  _dbus_user_database_lock_system (void)
595  {
596 -  _DBUS_LOCK (system_users);
597 -  database_locked = TRUE;
598 +  if (_DBUS_LOCK (system_users))
599 +    {
600 +      database_locked = TRUE;
601 +      return TRUE;
602 +    }
603 +  else
604 +    {
605 +      return FALSE;
606 +    }
607  }
608  
609  /**
610 @@ -345,8 +352,12 @@ _dbus_user_database_get_system (void)
611  void
612  _dbus_user_database_flush_system (void)
613  {
614 -  _dbus_user_database_lock_system ();
615 -   
616 +  if (!_dbus_user_database_lock_system ())
617 +    {
618 +      /* nothing to flush */
619 +      return;
620 +    }
621 +
622     if (system_db != NULL)
623      _dbus_user_database_flush (system_db);
624  
625 @@ -363,7 +374,9 @@ _dbus_user_database_flush_system (void)
626  dbus_bool_t
627  _dbus_username_from_current_process (const DBusString **username)
628  {
629 -  _dbus_user_database_lock_system ();
630 +  if (!_dbus_user_database_lock_system ())
631 +    return FALSE;
632 +
633    if (!init_system_db ())
634      {
635        _dbus_user_database_unlock_system ();
636 @@ -385,7 +398,9 @@ _dbus_username_from_current_process (const DBusString **username)
637  dbus_bool_t
638  _dbus_homedir_from_current_process (const DBusString  **homedir)
639  {
640 -  _dbus_user_database_lock_system ();
641 +  if (!_dbus_user_database_lock_system ())
642 +    return FALSE;
643 +
644    if (!init_system_db ())
645      {
646        _dbus_user_database_unlock_system ();
647 @@ -410,7 +425,10 @@ _dbus_homedir_from_username (const DBusString *username,
648  {
649    DBusUserDatabase *db;
650    const DBusUserInfo *info;
651 -  _dbus_user_database_lock_system ();
652 +
653 +  /* FIXME: this can't distinguish ENOMEM from other errors */
654 +  if (!_dbus_user_database_lock_system ())
655 +    return FALSE;
656  
657    db = _dbus_user_database_get_system ();
658    if (db == NULL)
659 @@ -449,7 +467,10 @@ _dbus_homedir_from_uid (dbus_uid_t         uid,
660  {
661    DBusUserDatabase *db;
662    const DBusUserInfo *info;
663 -  _dbus_user_database_lock_system ();
664 +
665 +  /* FIXME: this can't distinguish ENOMEM from other errors */
666 +  if (!_dbus_user_database_lock_system ())
667 +    return FALSE;
668  
669    db = _dbus_user_database_get_system ();
670    if (db == NULL)
671 @@ -496,7 +517,9 @@ _dbus_credentials_add_from_user (DBusCredentials  *credentials,
672    DBusUserDatabase *db;
673    const DBusUserInfo *info;
674  
675 -  _dbus_user_database_lock_system ();
676 +  /* FIXME: this can't distinguish ENOMEM from other errors */
677 +  if (!_dbus_user_database_lock_system ())
678 +    return FALSE;
679  
680    db = _dbus_user_database_get_system ();
681    if (db == NULL)
682 diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h
683 index cb49d9e..d6b72d8 100644
684 --- a/dbus/dbus-userdb.h
685 +++ b/dbus/dbus-userdb.h
686 @@ -86,7 +86,7 @@ void           _dbus_group_info_free_allocated  (DBusGroupInfo    *info);
687  #endif /* DBUS_USERDB_INCLUDES_PRIVATE */
688  
689  DBusUserDatabase* _dbus_user_database_get_system    (void);
690 -void              _dbus_user_database_lock_system   (void);
691 +dbus_bool_t       _dbus_user_database_lock_system   (void) _DBUS_GNUC_WARN_UNUSED_RESULT;
692  void              _dbus_user_database_unlock_system (void);
693  void              _dbus_user_database_flush_system  (void);
694  
695 diff --git a/test/name-test/test-threads-init.c b/test/name-test/test-threads-init.c
696 index 5e22852..580ffe1 100644
697 --- a/test/name-test/test-threads-init.c
698 +++ b/test/name-test/test-threads-init.c
699 @@ -149,11 +149,15 @@ main (int argc, char *argv[])
700                                           &dispatch_cond1,
701                                           &io_path_cond1);
702  
703 -  check_mutex_lock (mutex1, mutex2, FALSE);
704 -  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, FALSE);
705 -  check_mutex_lock (io_path_mutex1, io_path_mutex2, FALSE);
706 -  check_condvar_lock (dispatch_cond1, dispatch_cond2, FALSE);
707 -  check_condvar_lock (io_path_cond1, io_path_cond2, FALSE);
708 +  /* Since 1.7 it is no longer the case that mutex1 != mutex2, because
709 +   * initializing global locks automatically initializes locks
710 +   * in general. However, it is true that the mutex is not the dummy
711 +   * implementation, which is what we really wanted to check here. */
712 +  _dbus_assert (mutex1 != (DBusMutex *) 0xABCDEF);
713 +  _dbus_assert (dispatch_mutex1 != (DBusMutex *) 0xABCDEF);
714 +  _dbus_assert (dispatch_cond1 != (DBusCondVar *) 0xABCDEF2);
715 +  _dbus_assert (io_path_mutex1 != (DBusMutex *) 0xABCDEF);
716 +  _dbus_assert (io_path_cond1 != (DBusCondVar *) 0xABCDEF2);
717  
718    _run_iteration (conn);
719    _dbus_connection_test_get_locks (conn, &mutex2,