Changeset 689dd889dee2ea43e8a7cb64ccec0b923a8a60bd
- Timestamp:
- 28/01/08 18:01:48
(9 months ago)
- Author:
- Rémi Denis-Courmont <rem@videolan.org>
- git-committer:
- Rémi Denis-Courmont <rem@videolan.org> 1201539708 +0000
- git-parent:
[e15891a3316a7b2c3fc0480fd5ff8f18858d8802]
- git-author:
- Rémi Denis-Courmont <rem@videolan.org> 1201539708 +0000
- Message:
Only use waitpipe for _kill, rather than _signal, which is what people expect
(You really don't usually want your net_Read/net_Write to interrupted).
In the process, fix a deadlock in vlc_cond_wait() when waitpipe is used - fixes #1448
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| rd9b5111 |
r689dd88 |
|
| 110 | 110 | |
|---|
| 111 | 111 | /* Objects thread synchronization */ |
|---|
| 112 | | vlc_bool_t b_signaled; |
|---|
| 113 | 112 | int pipes[2]; |
|---|
| 114 | 113 | vlc_spinlock_t spin; |
|---|
| rb941c1e |
r689dd88 |
|
| 451 | 451 | vlc_cond_destroy( &p_this->object_wait ); |
|---|
| 452 | 452 | vlc_spin_destroy( &p_priv->spin ); |
|---|
| | 453 | if( p_priv->pipes[1] != -1 ) |
|---|
| | 454 | close( p_priv->pipes[1] ); |
|---|
| 453 | 455 | if( p_priv->pipes[0] != -1 ) |
|---|
| 454 | 456 | close( p_priv->pipes[0] ); |
|---|
| 455 | | if( p_priv->pipes[1] != -1 ) |
|---|
| 456 | | close( p_priv->pipes[1] ); |
|---|
| 457 | 457 | |
|---|
| 458 | 458 | /* global is not dynamically allocated by vlc_object_create */ |
|---|
| … | … | |
| 529 | 529 | |
|---|
| 530 | 530 | /** |
|---|
| 531 | | * Returns the readable end of a pipe that becomes readable whenever |
|---|
| 532 | | * an object is signaled. This can be used to wait for VLC object events |
|---|
| 533 | | * inside select(), poll() loops or frameworks providing an event loop. |
|---|
| | 531 | * Returns the readable end of a pipe that becomes readable once termination |
|---|
| | 532 | * of the object is requested (vlc_object_kill()). |
|---|
| | 533 | * This can be used to wake-up out of a select() or poll() event loop, such |
|---|
| | 534 | * typically when doing network I/O. |
|---|
| 534 | 535 | * |
|---|
| 535 | 536 | * Note that the pipe will remain the same for the lifetime of the object. |
|---|
| 536 | | * DO NOT close it yourself. Ever. |
|---|
| | 537 | * DO NOT read the pipe nor close it yourself. Ever. |
|---|
| 537 | 538 | * |
|---|
| 538 | | * DO NOT try to read from the pipe either: call vlc_object_wait() instead. |
|---|
| 539 | | * Assuming the pipe is readable, vlc_object_wait() will not block. |
|---|
| 540 | | * Also note that, as with vlc_object_wait(), there may be spurious wakeups. |
|---|
| 541 | | * |
|---|
| 542 | | * @param obj object that would be signaled |
|---|
| | 539 | * @param obj object that would be "killed" |
|---|
| 543 | 540 | * @return a readable pipe descriptor, or -1 on error. |
|---|
| 544 | 541 | */ |
|---|
| … | … | |
| 547 | 544 | int pfd[2] = { -1, -1 }; |
|---|
| 548 | 545 | struct vlc_object_internals_t *internals = obj->p_internals; |
|---|
| 549 | | vlc_bool_t race = VLC_FALSE, signaled = VLC_FALSE; |
|---|
| | 546 | vlc_bool_t killed = VLC_FALSE; |
|---|
| 550 | 547 | |
|---|
| 551 | 548 | vlc_spin_lock (&internals->spin); |
|---|
| … | … | |
| 560 | 557 | |
|---|
| 561 | 558 | vlc_spin_lock (&internals->spin); |
|---|
| 562 | | signaled = internals->b_signaled; |
|---|
| 563 | 559 | if (internals->pipes[0] == -1) |
|---|
| 564 | 560 | { |
|---|
| 565 | 561 | internals->pipes[0] = pfd[0]; |
|---|
| 566 | 562 | internals->pipes[1] = pfd[1]; |
|---|
| 567 | | } |
|---|
| 568 | | else |
|---|
| 569 | | race = VLC_TRUE; |
|---|
| | 563 | pfd[0] = pfd[1] = -1; |
|---|
| | 564 | } |
|---|
| | 565 | killed = obj->b_die; |
|---|
| 570 | 566 | } |
|---|
| 571 | 567 | vlc_spin_unlock (&internals->spin); |
|---|
| 572 | 568 | |
|---|
| 573 | | if (race) |
|---|
| 574 | | { /* Race condition: two threads call pipe() - unlikely */ |
|---|
| | 569 | if (killed) |
|---|
| | 570 | { |
|---|
| | 571 | /* Race condition: vlc_object_kill() already invoked! */ |
|---|
| | 572 | int fd; |
|---|
| | 573 | |
|---|
| | 574 | vlc_spin_lock (&internals->spin); |
|---|
| | 575 | fd = internals->pipes[1]; |
|---|
| | 576 | internals->pipes[1] = -1; |
|---|
| | 577 | vlc_spin_unlock (&internals->spin); |
|---|
| | 578 | if (fd != -1) |
|---|
| | 579 | close (fd); |
|---|
| | 580 | } |
|---|
| | 581 | |
|---|
| | 582 | /* Race condition: two threads call pipe() - unlikely */ |
|---|
| | 583 | if (pfd[0] != -1) |
|---|
| 575 | 584 | close (pfd[0]); |
|---|
| | 585 | if (pfd[1] != -1) |
|---|
| 576 | 586 | close (pfd[1]); |
|---|
| 577 | | } |
|---|
| 578 | | |
|---|
| 579 | | if (signaled) |
|---|
| 580 | | /* Race condition: lc_object_signal() already invoked! */ |
|---|
| 581 | | while (write (internals->pipes[1], &(char){ 0 }, 1) < 0); |
|---|
| 582 | 587 | |
|---|
| 583 | 588 | return internals->pipes[0]; |
|---|
| … | … | |
| 594 | 599 | vlc_bool_t __vlc_object_wait( vlc_object_t *obj ) |
|---|
| 595 | 600 | { |
|---|
| 596 | | int fd; |
|---|
| 597 | | |
|---|
| 598 | 601 | vlc_assert_locked( &obj->object_lock ); |
|---|
| 599 | | |
|---|
| 600 | | fd = obj->p_internals->pipes[0]; |
|---|
| 601 | | if (fd != -1) |
|---|
| 602 | | { |
|---|
| 603 | | while (read (fd, &(char){ 0 }, 1) < 0); |
|---|
| 604 | | return obj->b_die; |
|---|
| 605 | | } |
|---|
| 606 | | |
|---|
| 607 | 602 | vlc_cond_wait( &obj->object_wait, &obj->object_lock ); |
|---|
| 608 | | obj->p_internals->b_signaled = VLC_FALSE; |
|---|
| 609 | 603 | return obj->b_die; |
|---|
| 610 | 604 | } |
|---|
| … | … | |
| 668 | 662 | void __vlc_object_signal_unlocked( vlc_object_t *obj ) |
|---|
| 669 | 663 | { |
|---|
| 670 | | struct vlc_object_internals_t *internals = obj->p_internals; |
|---|
| 671 | | int fd; |
|---|
| 672 | | |
|---|
| 673 | 664 | vlc_assert_locked (&obj->object_lock); |
|---|
| 674 | | |
|---|
| 675 | | vlc_spin_lock (&internals->spin); |
|---|
| 676 | | fd = internals->pipes[1]; |
|---|
| 677 | | internals->b_signaled = VLC_TRUE; |
|---|
| 678 | | vlc_spin_unlock (&internals->spin); |
|---|
| 679 | | |
|---|
| 680 | | if( fd != -1 ) |
|---|
| 681 | | while( write( fd, &(char){ 0 }, 1 ) < 0 ); |
|---|
| 682 | | |
|---|
| 683 | 665 | vlc_cond_signal( &obj->object_wait ); |
|---|
| 684 | 666 | } |
|---|
| … | … | |
| 691 | 673 | void __vlc_object_kill( vlc_object_t *p_this ) |
|---|
| 692 | 674 | { |
|---|
| | 675 | struct vlc_object_internals_t *internals = p_this->p_internals; |
|---|
| | 676 | int fd; |
|---|
| | 677 | |
|---|
| 693 | 678 | vlc_mutex_lock( &p_this->object_lock ); |
|---|
| 694 | 679 | p_this->b_die = VLC_TRUE; |
|---|
| | 680 | |
|---|
| | 681 | vlc_spin_lock (&internals->spin); |
|---|
| | 682 | fd = internals->pipes[1]; |
|---|
| | 683 | internals->pipes[1] = -1; |
|---|
| | 684 | vlc_spin_unlock (&internals->spin); |
|---|
| | 685 | |
|---|
| | 686 | if( fd != -1 ) |
|---|
| | 687 | close (fd); |
|---|
| 695 | 688 | |
|---|
| 696 | 689 | if( p_this->i_object_type == VLC_OBJECT_LIBVLC ) |
|---|