Bug 151767 - pthread_mutex_init returns success with bad attributes; SUBSEQUENT operations fail
Summary: pthread_mutex_init returns success with bad attributes; SUBSEQUENT operations...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: threads (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-threads (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-10-27 00:20 UTC by Mark Terribile
Modified: 2020-07-07 00:50 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Terribile 2010-10-27 00:20:06 UTC
1) A pthread_mutexattr_t is initialized and then parameters are set.  Some are unsupported or invalid, as shown below.  All the operations return success.

2) The pthread_mutex_attr_t is used in the initialization of a pthread_mutex_t.  The pthread_mutex_init returns success.

3) A subesequent operation (pthread_mutex_lock, pthread_mutex_destroy) on the mutex in question returns EINVAL.

This delayed reporting makes finding an error very difficult, and is probably not correct.  Can the pthread_mutex_init be said to succeed if the mutex cannot be used for anything without generating an EINVAL?

I understand that 7.2 is not a supported release, but this problem does not seem to appear in the bug reports so it is likely also present in later releases.  An upgrade at this site right now is not feasible; I need a very stable environment underneath me.

How-To-Repeat: Please refer to the code below.  All operations up to the #if return 0.  If the lock/unlock code is #if'd out, the pthread_mutex_destroy returns 22.  If the lock/unlock code is #if'd in, the pthread_mutex_lock returns 22, the pthread_mutex_unlock returns 2 (probably correct, given the other errors) and the pthread_mutex_destroy still returns 22.


#include <stdio.h>
#include <pthread.h>

int main()
{
	pthread_mutexattr_t ma;

	int r = pthread_mutexattr_init( &ma );

	printf( "mutexattr init %d\n", r );

	r = pthread_mutexattr_setprotocol( &ma, PTHREAD_PRIO_PROTECT );

	printf( "mutexattr setprotocol %d\n", r );

	r = pthread_mutexattr_settype( &ma, PTHREAD_MUTEX_ERRORCHECK );

	printf( "mutexattr settype %d\n", r );

	r = pthread_mutexattr_setprioceiling( &ma, 2 );

	printf( "mutexattr setprioceiling %d\n", r );

	pthread_mutex_t mtx;

	r = pthread_mutex_init( &mtx, &ma );

	printf( "mutex init %d\n", r );

#if 0
	r = pthread_mutex_lock( &mtx );

	printf( "mutex lock %d\n", r );

	r = pthread_mutex_unlock( &mtx );

	printf( "mutex unlock %d\n", r );
#endif

	r = pthread_mutex_destroy( &mtx );

	printf( "mutex destroy %d\n", r );

	return 0;
}
Comment 1 Mark Terribile 2010-10-27 03:27:29 UTC
=0ADavid,=0A=0A> Mark Terribile wrote:=0A ...=0A> > 1) A pthread_mutexattr_=
t is initialized and then=0A> parameters are set.=A0 Some are unsupported o=
r invalid,=0A> as shown below.=A0 All the operations return success.=0A ...=
=0A> > 2) The pthread_mutex_attr_t is used in the=0A> initialization of a p=
thread_mutex_t.=A0 The=0A> pthread_mutex_init returns success.=0A ...=0A> >=
 3) A subesequent operation (pthread_mutex_lock,=0A> pthread_mutex_destroy)=
 on the mutex in question returns=0A> EINVAL.=0A=0A> Long time ago, I had r=
eported the priority issue in ULE=0A> scheduler,=0A> the scheduler incorrec=
tly changed a time-sharing thread to=0A> real-time=0A> priority when it ret=
urns to userland if it thinks it is=0A> interactive.=0A> so you can not use=
 prority protected mutex with ULE=0A> scheduler.=0A> see sched_ule.c:=0A=0A=
David,=0A=0AThis isn't a critical problem for me.  I ran into it while chec=
king=0Amy own error-handling code.  It's always a tricky business to MAKE=
=0Athings go wrong to test it.=0A=0AAnd I have no problem with the priority=
 protected mutex being unavailable=0A(though others might).  The problem fo=
r me is that the initialization=0Asuceeds, but then every subsequent operat=
ion fails.  If you have code that=0Aassumes that a failure in pthread_mutex=
_destroy() means a very sick=0Aprogram, you'll react the wrong way to an er=
ror of this sort.  And tracing=0Ait to the source cost me most of a day, ev=
en though I was doing nothing=0Abut testing some wrappers on pthreads.=0A=
=0ASo while this error is officially non-critical, it can cost a great deal=
=0Aof time.  It is a bizarre failure-at-a-distance for parameters that can=
=0Aand should be checked--and probably are, but maybe not completely enough=
.=0A=0ABut it's good to know that it reflects an underlying problem whose r=
oot=0Acause is known.  Thanks for explaining it.=0A=0A    Mark Terribile=0A=
=0A=0A
Comment 2 David Xu freebsd_committer 2010-10-27 10:54:55 UTC
Long time ago, I had reported the priority issue in ULE scheduler,
the scheduler incorrectly changed a time-sharing thread to real-time
priority when it returns to userland if it thinks it is interactive.
so you can not use prority protected mutex with ULE scheduler.
see sched_ule.c:

>  /*
>          * If the score is interactive we place the thread in the realtime
>          * queue with a priority that is less than kernel and interrupt
>          * priorities.  These threads are not subject to nice restrictions.
>          *
>          * Scores greater than this are placed on the normal timeshare queue
>          * where the priority is partially decided by the most recent cpu
>          * utilization and the rest is decided by nice value.
>          *
>          * The nice value of the process has a linear effect on the calculated
>          * score.  Negative nice values make it easier for a thread to be
>          * considered interactive.
>          */
>         score = imax(0, sched_interact_score(td) + td->td_proc->p_nice);
>         if (score < sched_interact) {
>                 pri = PRI_MIN_REALTIME;
>                 pri += ((PRI_MAX_REALTIME - PRI_MIN_REALTIME) / sched_interact)
>                     * score;
>                 KASSERT(pri >= PRI_MIN_REALTIME && pri <= PRI_MAX_REALTIME,
>                     ("sched_priority: invalid interactive priority %d score %d",
>                     pri, score));
>         } else {
>                 pri = SCHED_PRI_MIN;
>                 if (td->td_sched->ts_ticks)
>                         pri += SCHED_PRI_TICKS(td->td_sched);
>                 pri += SCHED_PRI_NICE(td->td_proc->p_nice);
>                 KASSERT(pri >= PRI_MIN_TIMESHARE && pri <= PRI_MAX_TIMESHARE,
>                     ("sched_priority: invalid priority %d: nice %d, "
>                     "ticks %d ftick %d ltick %d tick pri %d",
>                     pri, td->td_proc->p_nice, td->td_sched->ts_ticks,
>                     td->td_sched->ts_ftick, td->td_sched->ts_ltick,
>                     SCHED_PRI_TICKS(td->td_sched)));
>         }
>         sched_user_prio(td, pri);
> 
>         return;
> }


However, I may remove trylock in pthread_mutex_destroy, because it
does not help anything if there is a programming bug in application.
Comment 3 Alexander Best freebsd_committer 2010-10-27 12:37:19 UTC
State Changed
From-To: open->patched

Patched in HEAD (r214410). 


Comment 4 Alexander Best freebsd_committer 2010-10-27 12:37:19 UTC
Responsible Changed
From-To: freebsd-threads->davidxu

Assign to David as MFC reminder.
Comment 5 Mark Linimon 2010-11-20 11:53:54 UTC
----- Forwarded message from David Xu <davidxu@freebsd.org> -----

From: David Xu <davidxu@freebsd.org>
To: Daniel Eischen <deischen@freebsd.org>
Cc: freebsd-threads@freebsd.org
Subject: Re: threads/151767: pthread_mutex_init returns success with bad
	attributes; SUBSEQUENT operations fail

There is no priority bug in libthr with the pp mutex or pi mutex,
it is the kernel scheduler has incorrectly set a time-sharing
thread priority to real-time, that's culprit.
the time-sharing is simply a rr scheduling, or a correctly
implemented rr scheduling. in umtx, all time-sharing thread
has same priority, just one priority, the priority is lower than
any other real-time priorities. the time-sharing thread should
be abole to use pp or pi mutex without any problem.

this is what POSIX said:
> EINVAL]
>     The mutex was created with the protocol attribute having the
>
> value PTHREAD_PRIO_PROTECT and the calling thread's priority is
> higher than the mutex's current priority ceiling.

The culprit is that ULE sets a time-sharing thread's priority
to 138 or 139 in the bug-reporter's code, which causes
umtx code found that the thread violates the standard and
aborted.

----- End forwarded message -----
Comment 6 Daniel Eischen freebsd_committer 2012-01-16 16:13:46 UTC
State Changed
From-To: patched->feedback

Can we close this bug?
Comment 7 David Xu freebsd_committer 2014-04-14 09:15:00 UTC
Responsible Changed
From-To: davidxu->deischen

Assign this pr to de@
Comment 8 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:00:48 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 9 Mark Johnston freebsd_committer 2020-07-07 00:50:58 UTC
The original sample code no longer triggers any errors as of r216791, which fixed a scheduler bug triggered by the sample.  From what I can see in the corresponding pthread function implementations, we do sufficient validation of all of the mutex attributes, so I'm going to resolve this as FIXED.