Changeset 234a17d087d4b5648adb9051a847db31bbc47149
- Timestamp:
- 30/05/08 17:18:02
(4 months ago)
- Author:
- Rémi Denis-Courmont <rem@videolan.org>
- git-committer:
- Rémi Denis-Courmont <rem@videolan.org> 1212160682 +0300
- git-parent:
[7a826ae225a087ddeee5993e5230878dd2ded7c5]
- git-author:
- Rémi Denis-Courmont <rem@videolan.org> 1212160465 +0300
- Message:
Improve the still really dumb reference checker
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r523ef30 |
r234a17d |
|
| 188 | 188 | unsigned i_refcount; |
|---|
| 189 | 189 | vlc_destructor_t pf_destructor; |
|---|
| | 190 | #ifndef NDEBUG |
|---|
| | 191 | vlc_thread_t creator_id; |
|---|
| | 192 | #endif |
|---|
| 190 | 193 | |
|---|
| 191 | 194 | /* Objects tree structure */ |
|---|
| r85fa3c2 |
r234a17d |
|
| 172 | 172 | |
|---|
| 173 | 173 | p_priv->next = VLC_OBJECT (p_libvlc_global); |
|---|
| | 174 | #if defined (NDEBUG) |
|---|
| | 175 | /* ... */ |
|---|
| | 176 | #elif defined (LIBVLC_USE_PTRHEAD) |
|---|
| | 177 | p_priv->creator_id = pthread_self (); |
|---|
| | 178 | #elif defined (WIN32) |
|---|
| | 179 | p_priv->creator_id = GetCurrentThreadId (); |
|---|
| | 180 | #endif |
|---|
| 174 | 181 | vlc_mutex_lock( &structure_lock ); |
|---|
| 175 | 182 | p_priv->prev = vlc_internals (p_libvlc_global)->prev; |
|---|
| … | … | |
| 1482 | 1489 | |
|---|
| 1483 | 1490 | #ifndef NDEBUG |
|---|
| | 1491 | # ifdef __GLIBC__ |
|---|
| | 1492 | # include <execinfo.h> |
|---|
| | 1493 | # endif |
|---|
| | 1494 | |
|---|
| 1484 | 1495 | void vlc_refcheck (vlc_object_t *obj) |
|---|
| 1485 | 1496 | { |
|---|
| 1486 | 1497 | static unsigned errors = 0; |
|---|
| 1487 | | vlc_object_t *caller = vlc_threadobj (); |
|---|
| 1488 | | vlc_object_internals_t *priv = vlc_internals (obj); |
|---|
| 1489 | | int refs; |
|---|
| 1490 | | |
|---|
| 1491 | 1498 | if (errors > 100) |
|---|
| 1492 | 1499 | return; |
|---|
| 1493 | 1500 | |
|---|
| 1494 | | if (!caller) |
|---|
| 1495 | | return; /* main thread, not sure how to handle it */ |
|---|
| 1496 | | |
|---|
| 1497 | | /* An object can always access itself without reference! */ |
|---|
| | 1501 | /* Anyone can use the root object (though it should not exist) */ |
|---|
| | 1502 | if (obj == VLC_OBJECT (vlc_global ())) |
|---|
| | 1503 | return; |
|---|
| | 1504 | |
|---|
| | 1505 | /* Anyone can use its libvlc instance object */ |
|---|
| | 1506 | if (obj == VLC_OBJECT (obj->p_libvlc)) |
|---|
| | 1507 | return; |
|---|
| | 1508 | |
|---|
| | 1509 | /* The thread that created the object holds the initial reference */ |
|---|
| | 1510 | vlc_object_internals_t *priv = vlc_internals (obj); |
|---|
| | 1511 | #if defined (LIBVLC_USE_PTHREAD) |
|---|
| | 1512 | if (pthread_equal (priv->creator_id, pthread_self ())) |
|---|
| | 1513 | #elif defined WIN32 |
|---|
| | 1514 | if (priv->creator_id == GetCurrentThreadId ()) |
|---|
| | 1515 | #else |
|---|
| | 1516 | if (0) |
|---|
| | 1517 | #endif |
|---|
| | 1518 | return; |
|---|
| | 1519 | |
|---|
| | 1520 | /* A thread can use its own object without reference! */ |
|---|
| | 1521 | vlc_object_t *caller = vlc_threadobj (); |
|---|
| 1498 | 1522 | if (caller == obj) |
|---|
| 1499 | 1523 | return; |
|---|
| 1500 | 1524 | |
|---|
| 1501 | 1525 | /* The calling thread is younger than the object. |
|---|
| 1502 | | * Access could be valid, we would need more accounting. */ |
|---|
| 1503 | | if (caller->i_object_id > obj->i_object_id) |
|---|
| | 1526 | * Access could be valid through cross-thread synchronization; |
|---|
| | 1527 | * we would need better accounting. */ |
|---|
| | 1528 | if (caller && (caller->i_object_id > obj->i_object_id)) |
|---|
| 1504 | 1529 | return; |
|---|
| 1505 | 1530 | |
|---|
| | 1531 | int refs; |
|---|
| 1506 | 1532 | vlc_spin_lock (&priv->ref_spin); |
|---|
| 1507 | 1533 | refs = priv->i_refcount; |
|---|
| … | … | |
| 1513 | 1539 | return; |
|---|
| 1514 | 1540 | |
|---|
| 1515 | | /* The parent of an object normally holds the unique reference. |
|---|
| 1516 | | * As not all objects are threads, it could also be an ancestor. */ |
|---|
| 1517 | | vlc_mutex_lock (&structure_lock); |
|---|
| 1518 | | for (vlc_object_t *cur = obj; cur != NULL; cur = cur->p_parent) |
|---|
| 1519 | | if (cur == caller) |
|---|
| 1520 | | { |
|---|
| 1521 | | vlc_mutex_unlock (&structure_lock); |
|---|
| 1522 | | return; |
|---|
| 1523 | | } |
|---|
| 1524 | | vlc_mutex_unlock (&structure_lock); |
|---|
| 1525 | | |
|---|
| 1526 | | #if 1 |
|---|
| 1527 | | if (caller->i_object_type == VLC_OBJECT_PLAYLIST) |
|---|
| 1528 | | return; /* Playlist is too clever, or hopelessly broken. */ |
|---|
| | 1541 | fprintf (stderr, "The %s %s thread object is accessing...\n" |
|---|
| | 1542 | "the %s %s object in a suspicous manner.\n", |
|---|
| | 1543 | caller && caller->psz_object_name |
|---|
| | 1544 | ? caller->psz_object_name : "unnamed", |
|---|
| | 1545 | caller ? caller->psz_object_type : "main", |
|---|
| | 1546 | obj->psz_object_name ? obj->psz_object_name : "unnamed", |
|---|
| | 1547 | obj->psz_object_type); |
|---|
| | 1548 | fflush (stderr); |
|---|
| | 1549 | |
|---|
| | 1550 | #ifdef __GLIBC__ |
|---|
| | 1551 | void *stack[20]; |
|---|
| | 1552 | int stackdepth = backtrace (stack, sizeof (stack) / sizeof (stack[0])); |
|---|
| | 1553 | backtrace_symbols_fd (stack, stackdepth, 2); |
|---|
| 1529 | 1554 | #endif |
|---|
| 1530 | | msg_Err (caller, "This thread is accessing..."); |
|---|
| 1531 | | msg_Err (obj, "...this object in a suspicious manner."); |
|---|
| 1532 | 1555 | |
|---|
| 1533 | 1556 | if (++errors == 100) |
|---|
| 1534 | | msg_Err (caller, "Too many reference errors"); |
|---|
| | 1557 | fprintf (stderr, "Too many reference errors!\n"); |
|---|
| 1535 | 1558 | } |
|---|
| 1536 | 1559 | #endif |
|---|