Changeset 5bd06c4b174082d6062e267565342c568ba6454d
- Timestamp:
- 30/08/08 09:21:45 (3 months ago)
- git-parent:
- Files:
-
- src/libvlc.h (modified) (2 diffs)
- src/misc/objects.c (modified) (7 diffs)
- src/misc/variables.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
src/libvlc.h
rd6c0f24 r5bd06c4 47 47 void vlc_threads_end( void ); 48 48 vlc_object_t *vlc_threadobj (void); 49 #ifdef LIBVLC_REFCHECK50 void vlc_refcheck (vlc_object_t *obj);51 #else52 # define vlc_refcheck( obj ) (void)053 #endif54 49 55 50 /* Hopefully, no need to export this. There is a new thread API instead. */ … … 191 186 unsigned i_refcount; 192 187 vlc_destructor_t pf_destructor; 193 #ifndef LIBVLC_REFCHECK194 vlc_thread_t creator_id;195 #endif196 188 197 189 /* Objects tree structure */ src/misc/objects.c
r1cc0014 r5bd06c4 84 84 static void vlc_object_destroy( vlc_object_t *p_this ); 85 85 static void vlc_object_detach_unlocked (vlc_object_t *p_this); 86 87 #ifdef LIBVLC_REFCHECK88 static vlc_threadvar_t held_objects;89 typedef struct held_list_t90 {91 struct held_list_t *next;92 vlc_object_t *obj;93 } held_list_t;94 static void held_objects_destroy (void *);95 #endif96 86 97 87 /***************************************************************************** … … 163 153 p_priv->next = p_priv->prev = p_new; 164 154 vlc_mutex_init( &structure_lock ); 165 #ifdef LIBVLC_REFCHECK166 /* TODO: use the destruction callback to track ref leaks */167 vlc_threadvar_create( &held_objects, held_objects_destroy );168 #endif169 155 } 170 156 else … … 195 181 196 182 p_priv->next = VLC_OBJECT (p_libvlc_global); 197 #if !defined (LIBVLC_REFCHECK)198 /* ... */199 #elif defined (LIBVLC_USE_PTHREAD)200 p_priv->creator_id = pthread_self ();201 #elif defined (WIN32)202 p_priv->creator_id = GetCurrentThreadId ();203 #endif204 183 vlc_mutex_lock( &structure_lock ); 205 184 p_priv->prev = vlc_internals (p_libvlc_global)->prev; … … 367 346 /* We are the global object ... no need to lock. */ 368 347 vlc_mutex_destroy( &structure_lock ); 369 #ifdef LIBVLC_REFCHECK370 held_objects_destroy( vlc_threadvar_get( &held_objects ) );371 vlc_threadvar_delete( &held_objects );372 #endif373 348 } 374 349 … … 758 733 internals->i_refcount++; 759 734 vlc_spin_unlock( &internals->ref_spin ); 760 #ifdef LIBVLC_REFCHECK761 /* Update the list of referenced objects */762 /* Using TLS, so no need to lock */763 /* The following line may leak memory if a thread leaks objects. */764 held_list_t *newhead = malloc (sizeof (*newhead));765 held_list_t *oldhead = vlc_threadvar_get (&held_objects);766 newhead->next = oldhead;767 newhead->obj = p_this;768 vlc_threadvar_set (&held_objects, newhead);769 #endif770 735 } 771 736 … … 778 743 vlc_object_internals_t *internals = vlc_internals( p_this ); 779 744 bool b_should_destroy; 780 781 #ifdef LIBVLC_REFCHECK782 /* Update the list of referenced objects */783 /* Using TLS, so no need to lock */784 for (held_list_t *hlcur = vlc_threadvar_get (&held_objects),785 *hlprev = NULL;786 hlcur != NULL;787 hlprev = hlcur, hlcur = hlcur->next)788 {789 if (hlcur->obj == p_this)790 {791 if (hlprev == NULL)792 vlc_threadvar_set (&held_objects, hlcur->next);793 else794 hlprev->next = hlcur->next;795 free (hlcur);796 break;797 }798 }799 /* TODO: what if releasing without references? */800 #endif801 745 802 746 vlc_spin_lock( &internals->ref_spin ); … … 1489 1433 } 1490 1434 } 1491 1492 #ifdef LIBVLC_REFCHECK1493 # if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE)1494 # include <execinfo.h>1495 # endif1496 1497 void vlc_refcheck (vlc_object_t *obj)1498 {1499 static unsigned errors = 0;1500 if (errors > 100)1501 return;1502 1503 /* Anyone can use the root object (though it should not exist) */1504 if (obj == VLC_OBJECT (vlc_global ()))1505 return;1506 1507 /* Anyone can use its libvlc instance object */1508 if (obj == VLC_OBJECT (obj->p_libvlc))1509 return;1510 1511 /* The thread that created the object holds the initial reference */1512 vlc_object_internals_t *priv = vlc_internals (obj);1513 #if defined (LIBVLC_USE_PTHREAD)1514 if (pthread_equal (priv->creator_id, pthread_self ()))1515 #elif defined WIN321516 if (priv->creator_id == GetCurrentThreadId ())1517 #else1518 if (0)1519 #endif1520 return;1521 1522 /* A thread can use its own object without references! */1523 vlc_object_t *caller = vlc_threadobj ();1524 if (caller == obj)1525 return;1526 #if 01527 /* The calling thread is younger than the object.1528 * Access could be valid through cross-thread synchronization;1529 * we would need better accounting. */1530 if (caller && (caller->i_object_id > obj->i_object_id))1531 return;1532 #endif1533 int refs;1534 vlc_spin_lock (&priv->ref_spin);1535 refs = priv->i_refcount;1536 vlc_spin_unlock (&priv->ref_spin);1537 1538 for (held_list_t *hlcur = vlc_threadvar_get (&held_objects);1539 hlcur != NULL; hlcur = hlcur->next)1540 if (hlcur->obj == obj)1541 return;1542 1543 int canc = vlc_savecancel ();1544 1545 fprintf (stderr, "The %s %s thread object is accessing...\n"1546 "the %s %s object without references.\n",1547 caller && caller->psz_object_name1548 ? caller->psz_object_name : "unnamed",1549 caller ? caller->psz_object_type : "main",1550 obj->psz_object_name ? obj->psz_object_name : "unnamed",1551 obj->psz_object_type);1552 fflush (stderr);1553 1554 #ifdef HAVE_BACKTRACE1555 void *stack[20];1556 int stackdepth = backtrace (stack, sizeof (stack) / sizeof (stack[0]));1557 backtrace_symbols_fd (stack, stackdepth, 2);1558 #endif1559 1560 if (++errors == 100)1561 fprintf (stderr, "Too many reference errors!\n");1562 vlc_restorecancel (canc);1563 }1564 1565 static void held_objects_destroy (void *data)1566 {1567 VLC_UNUSED( data );1568 held_list_t *hl = vlc_threadvar_get (&held_objects);1569 vlc_object_t *caller = vlc_threadobj ();1570 1571 int canc = vlc_savecancel ();1572 1573 while (hl != NULL)1574 {1575 held_list_t *buf = hl->next;1576 vlc_object_t *obj = hl->obj;1577 1578 fprintf (stderr, "The %s %s thread object leaked a reference to...\n"1579 "the %s %s object.\n",1580 caller && caller->psz_object_name1581 ? caller->psz_object_name : "unnamed",1582 caller ? caller->psz_object_type : "main",1583 obj->psz_object_name ? obj->psz_object_name : "unnamed",1584 obj->psz_object_type);1585 free (hl);1586 hl = buf;1587 }1588 vlc_restorecancel (canc);1589 }1590 #endifsrc/misc/variables.c
r6cd4550 r5bd06c4 169 169 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 170 170 171 vlc_refcheck( p_this );172 171 vlc_mutex_lock( &p_priv->var_lock ); 173 172 … … 333 332 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 334 333 335 vlc_refcheck( p_this );336 334 vlc_mutex_lock( &p_priv->var_lock ); 337 335 … … 410 408 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 411 409 412 vlc_refcheck( p_this );413 410 vlc_mutex_lock( &p_priv->var_lock ); 414 411 … … 751 748 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 752 749 753 vlc_refcheck( p_this );754 750 vlc_mutex_lock( &p_priv->var_lock ); 755 751 … … 829 825 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 830 826 831 vlc_refcheck( p_this );832 827 vlc_mutex_lock( &p_priv->var_lock ); 833 828 … … 896 891 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 897 892 898 vlc_refcheck( p_this );899 893 entry.pf_callback = pf_callback; 900 894 entry.p_data = p_data; … … 934 928 vlc_object_internals_t *p_priv = vlc_internals( p_this ); 935 929 936 vlc_refcheck( p_this );937 930 vlc_mutex_lock( &p_priv->var_lock ); 938 931 … … 1571 1564 } 1572 1565 1573 vlc_refcheck( p_this );1574 1566 i_type = var_Type( p_obj, psz_cmd ); 1575 1567 if( !( i_type&VLC_VAR_ISCOMMAND ) )
