Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Lock a file with timeout

8 views
Skip to first unread message

A

unread,
Feb 27, 2008, 2:17:01 PM2/27/08
to
Hi,

I need a function that will attempt to lock a file handle with a
timeout; e.g.
r = timeLock(fd, tsec);

if the lock (using lockf()) can be obtained within tsecs
then r will be 0, else it will be -1.

I have an implementation for non-threaded programs using sigsetjmp
etc.
and would like a compatible pthreads implementation (for Solaris 9).

I've come up with the following using pthread_cond_timedwait
but it has two limitations
(a) it creates a thread for each call to the timeLock function
and would like to avoid that overhead
(b) it itself is non-threaded, i.e call to this need to be serialized

How could I improve on this?

Best regards

/* ++++++++++++++++++++++++++++++++++++++++ */
extern "C" {
typedef struct {
int fd;
pthread_cond_t *pc;
} lockStruct_t;
}

void *
thrLckFn(void *arg)
{
lockStruct_t * lp = (lockStruct_t*)arg;
lockf(lp->fd, F_LOCK, 0);
pthread_cond_signal(lp->pc);
return NULL;
}


int
timeLock(int fd, int tsecs)
{
if ( 0 == tsecs ) { return lockf(fd, F_TLOCK, 0); }

if ( 0 > tsecs ) { return lockf(fd, F_LOCK, 0); }

struct timespec t;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;

pthread_t thrLck;

lockStruct_t ls = {fd, &c};
t.tv_nsec = 0;

pthread_mutex_lock(&m);
t.tv_sec = time(NULL) + tsecs;

pthread_create(&thrLck, NULL, thrLckFn, &ls);
int r = pthread_cond_timedwait(&c, &m, &t);
pthread_mutex_unlock(&m);

if ( ETIMEDOUT == r ) {
pthread_cancel(thrLck);
return -1;
}

return r;
}
/*--------------------------------------------------------------------
*/

Maxim Yegorushkin

unread,
Feb 27, 2008, 3:01:14 PM2/27/08
to
On Feb 27, 10:17 pm, A <ad_...@yahoo.com> wrote:

> I need a function that will attempt to lock a file handle with a
> timeout; e.g.
>    r = timeLock(fd, tsec);
>
> if the lock (using lockf()) can be obtained within tsecs
> then r will be 0, else it will be -1.

http://www.opengroup.org/onlinepubs/009695399/functions/lockf.html
<quote>
The alarm() function may be used to provide a timeout facility in
applications requiring it.
</quote>

A

unread,
Feb 27, 2008, 3:40:40 PM2/27/08
to
On Feb 27, 3:01 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:

>
> http://www.opengroup.org/onlinepubs/009695399/functions/lockf.html
> <quote>
> The alarm() function may be used to provide a timeout facility in applications requiring it.
> </quote>

Yes, I am using the alarm() function along with sigsetjmp/siglongjmp
in the
un-threaded implementation but here I am looking for a thread-safe
mechanism.

A

unread,
Feb 27, 2008, 4:11:34 PM2/27/08
to
On Feb 27, 2:17 pm, A <ad_...@yahoo.com> wrote:
>
> (b) it itself is non-threaded, i.e call to this need to be serialized
>

Let me clarify this.

The function timeLock in the OP maybe called by multiple threads as
long as the fd's
do not refer to the same file. If they refer to the same file, then
all get the lock at the same time,
so second and subsequent calls always timeout.
This is due to the behaviour of fd's themselves,
thus, the timeLock function is thread-safe IFF the fd's refer to
distinct files,
otherwise calls to it should be serialized.

Thanks

Szabolcs Ferenczi

unread,
Feb 27, 2008, 4:24:40 PM2/27/08
to
On Feb 27, 8:17 pm, A <ad_...@yahoo.com> wrote:

> How could I improve on this?

1. You do not need to start any thread inside function `timeLock'

2. Extend the structure `lockStruct_t' with the mutex that will
protect that struct as a shared resource.

3. Introduce a shared variable (e.g. int locked;) in the structure
`lockStruct_t' that would represent the locked state (if it cannot be
checked otherwise)

4. Any time you access any field of structure `lockStruct_t', use the
associated mutex to protect it against concurrent access.

5. Do not use the condition variable for event signaling but use it to
indicate a change in the state of the associated shared variables. For
event signaling, if you need it, you should use semaphores.

6. Check out the documentation of the timed wait (with example)
http://www.opengroup.org/onlinepubs/000095399/functions/pthread_cond_timedwait.html

I hope this helps.

Best Regards,
Szabolcs

William Ahern

unread,
Feb 27, 2008, 4:29:41 PM2/27/08
to
A <ad_...@yahoo.com> wrote:
> On Feb 27, 3:01?pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>

> wrote:
> >
> > http://www.opengroup.org/onlinepubs/009695399/functions/lockf.html
> > <quote>
> > The alarm() function may be used to provide a timeout facility in applications requiring it.
> > </quote>

> Yes, I am using the alarm() function along with sigsetjmp/siglongjmp in
> the un-threaded implementation

Why are you jumping out of the signal handler? That's usually a very bad
idea, and shouldn't be necessary in this circumstance. After delivery of the
signal, lockf() should return with errno = EINTR.

William Ahern

unread,
Feb 27, 2008, 4:45:56 PM2/27/08
to
A <ad_...@yahoo.com> wrote:
> Hi,
>
> I need a function that will attempt to lock a file handle with a
> timeout; e.g.
> r = timeLock(fd, tsec);
>
> if the lock (using lockf()) can be obtained within tsecs
> then r will be 0, else it will be -1.
>
> I have an implementation for non-threaded programs using sigsetjmp etc.
> and would like a compatible pthreads implementation (for Solaris 9).

Why not do the same for the threaded version? Rather than spin off a thread
to call lockf, call lockf from the thread trying to get the lock, and
instead use another "alarm" thread. That thread will do a timed wait on a
condition variable. If it times out on the condition variable, that thread
will call pthread_kill(&lockf_thread, SIGALRM); otherwise, the conditional
variable would be used by the locking thread to signal it got the lock and
doesn't need the alarm anymore.

The original thread needs to check the return value of lockf, which you're
not doing anywhere in your posted code. Again, if it returns -1 and errno =
EINTR, then it timed out. Also, you'll need to set the SIGALRM handler
appropriately in all the threads which might call lockf(). Just install a
dud handler--one that just returns--because you just want the side effect of
interrupting lockf.

You'll need to synchronize those threads, though, so the alarm thread
doesn't timeout on the condition at the same time the locking thread gets
the lock, otherwise you'll get spurious SIGALARMs here or there.

Chris Thomasson

unread,
Feb 27, 2008, 5:16:24 PM2/27/08
to

"Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
news:e5fb9f1b-03b8-4311...@60g2000hsy.googlegroups.com...

On Feb 27, 8:17 pm, A <ad_...@yahoo.com> wrote:

> How could I improve on this?

[...]

> > 5. Do not use the condition variable for event signaling but use it to
> > indicate a change in the state of the associated shared variables. For
> > event signaling, if you need it, you should use semaphores.

[...]

NON-SENSE:

http://groups.google.com/group/comp.programming.threads/msg/a934807273c2d95b

http://groups.google.com/group/comp.programming.threads/msg/3c017578d62e0524


We have been over this before; a condvar can EASILY be used for custom event
signaling logic.

Szabolcs Ferenczi

unread,
Feb 27, 2008, 6:16:07 PM2/27/08
to
On Feb 27, 10:24 pm, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:
> 6. Check out the documentation of the timed wait (with example)http://www.opengroup.org/onlinepubs/000095399/functions/pthread_cond_...

7. Do not forget to implement a corresponding `timeUnLock' operation
where you give a signal on the associated condition variable when the
file is unlocked.

Best Regards,
Szabolcs

David Schwartz

unread,
Feb 27, 2008, 7:10:57 PM2/27/08
to

A wrote:

> I need a function that will attempt to lock a file handle with a
> timeout; e.g.
> r = timeLock(fd, tsec);
>
> if the lock (using lockf()) can be obtained within tsecs
> then r will be 0, else it will be -1.

Why do you need such a function? You want to do one thing if you can
get a lock within a certain amount of time and another thing if you
can't. What you don't need is a thread to sit around doing nothing in
the interim, so why are you designing that? If the interface requires
a thread to sit around waiting, consider than an implementation
detail, but don't make it part of the API.

The way I would do it is the following:

1) Use a timer class that provides for timers to be cancelled if
desired and passes to the timer handler whether the timer was fired or
was cancelled.

2) Set a timer for the amount timeout, set the timer handler and so
on.

3) Make a timeLock function that takes a file descriptor and a timer.
Have it fire the timer if/when it gets the lock.

4) In the timer handler, if the timer was cancelled, you know you have
the lock. If it fired, you know it timed out.

5) Make sure trying to cancel a timer long after it fired is harmless.

You can then implement the timeLock function using 'alarm' or a pool
of threads or whatever makes the most sense. But don't build the API
to require a thread to sit around waiting for another thread that sits
around waiting.

DS

Chris Thomasson

unread,
Feb 27, 2008, 8:42:58 PM2/27/08
to
"A" <ad_...@yahoo.com> wrote in message
news:b42c0376-87e1-42fd...@64g2000hsw.googlegroups.com...

> Hi,
>
> I need a function that will attempt to lock a file handle with a
> timeout; e.g.
[...]

> I've come up with the following using pthread_cond_timedwait
> but it has two limitations
> (a) it creates a thread for each call to the timeLock function
> and would like to avoid that overhead
> (b) it itself is non-threaded, i.e call to this need to be serialized
>
> How could I improve on this?
[...]

I believe that there is a race-condition in your code:


Thread A
_____________________________
void *
thrLckFn(void *arg)
{
1: lockStruct_t * lp = (lockStruct_t*)arg;
2: lockf(lp->fd, F_LOCK, 0);
3: pthread_cond_signal(lp->pc);
4: return NULL;
}


Thread B
_____________________________


int
timeLock(int fd, int tsecs)
{

[...]

1: pthread_mutex_lock(&m);
2: t.tv_sec = time(NULL) + tsecs;

3: pthread_create(&thrLck, NULL, thrLckFn, &ls);
4: int r = pthread_cond_timedwait(&c, &m, &t);
5: pthread_mutex_unlock(&m);

6: if ( ETIMEDOUT == r ) {
7: pthread_cancel(thrLck);
8: return -1;
}

9: return r;
}


Suppose the execution sequence goes like this:

B1
B2
B3
B4
A1
A2
B5
B6 -- r == ETIMEDOUT
A3 -- the file is locked
A4
B7
B8 -- Yikes!


The file would have been locked, but your timeLock function returns -1.

Am I missing something here?

Chris Thomasson

unread,
Feb 27, 2008, 9:09:28 PM2/27/08
to
"A" <ad_...@yahoo.com> wrote in message
news:b42c0376-87e1-42fd...@64g2000hsw.googlegroups.com...
> Hi,
>
> I need a function that will attempt to lock a file handle with a
> timeout; e.g.
> r = timeLock(fd, tsec);
>
> if the lock (using lockf()) can be obtained within tsecs
> then r will be 0, else it will be -1.
>
> I have an implementation for non-threaded programs using sigsetjmp
> etc.
> and would like a compatible pthreads implementation (for Solaris 9).
>
> I've come up with the following using pthread_cond_timedwait
> but it has two limitations
> (a) it creates a thread for each call to the timeLock function
> and would like to avoid that overhead
> (b) it itself is non-threaded, i.e call to this need to be serialized
>
> How could I improve on this?
[...]

Lets see if I can generate some laughs:

The most naive and hard-core retarded method would be to do something
foolish like this:


<code-sketch>
_______________________________________________________________
int timedlockf(int fd, off_t sz, int tsec) {
int tout = 0;
do {
int status = lockf(fd, F_TLOCK, sz);
if (! status) {
return 0;
} else if (status != EINTR &&
status != EACCES &&
status != EAGAIN) {
return status;
} else {
int repeat = 0;
while (usleep(250000) && (++repeat) < 100);
if (! ((++tout) % 4)) {
--tsec;
}
}
} while (tsec > 0);
return ETIMEDOUT;
}
_______________________________________________________________


;^)

A

unread,
Feb 27, 2008, 10:02:50 PM2/27/08
to
On Feb 27, 9:09 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
>
> Lets see if I can generate some laughs:
>

I have seen precisely this in use, that is
attempt F_TLOCK
sleep a bit
until timeout

Yes, I think you are right, there is a race condition in that logic.

For David Schwartz's question why I need such a function,
well, it models the application scenario pretty accurately
and is offered as a portable library function (in C and Perl).

Basically, I am trying to figure out how to break out of a blocking
call to
lockf(fd, F_LOCK)
and report that to the caller.

Best regards.

Chris Thomasson

unread,
Feb 27, 2008, 11:44:37 PM2/27/08
to

"A" <ad_...@yahoo.com> wrote in message
news:bf86a56b-ed5f-44d1...@d5g2000hsc.googlegroups.com...

> On Feb 27, 9:09 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
> >
> > Lets see if I can generate some laughs:
>

> I have seen precisely this in use, that is
> attempt F_TLOCK
> sleep a bit
> until timeout

Well, I guess it should work. However, worst case scenario is a full-blown
250 milli-second wait after a file gets unlocked.


> Yes, I think you are right, there is a race condition in that logic.

Just to clarify, I believe that there is indeed a race-condition in the
quick sample code you posted here:

http://groups.google.com/group/comp.programming.threads/msg/5905ace57c4324a9

I can't see a racer in the "naive" method I posted.


> For David Schwartz's question why I need such a function,
> well, it models the application scenario pretty accurately
> and is offered as a portable library function (in C and Perl).

> Basically, I am trying to figure out how to break out of a blocking
> call to
> lockf(fd, F_LOCK)
> and report that to the caller.

What type of timing granularity do you need? Are you only going to be
waiting in intervals equal to a second?

Chris Thomasson

unread,
Feb 27, 2008, 11:50:57 PM2/27/08
to
"Chris Thomasson" <cri...@comcast.net> wrote in message
news:raudnYf1-sGSp1va...@comcast.com...

>
> "A" <ad_...@yahoo.com> wrote in message
> news:bf86a56b-ed5f-44d1...@d5g2000hsc.googlegroups.com...
>> On Feb 27, 9:09 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
>> >
>> > Lets see if I can generate some laughs:
>>
>
>> I have seen precisely this in use, that is
>> attempt F_TLOCK
>> sleep a bit
>> until timeout
>
> Well, I guess it should work. However, worst case scenario is a full-blown
> 250 milli-second wait after a file gets unlocked.

[...]

Or, if usleep gets interrupted by signal. I guess a little hack would be to
trim a few microseconds off the wait time... Something like:

<code-sketch>
_______________________________________________________________
int timedlockf(int fd, off_t sz, int tsec) {
int tout = 0;
do {
int status = lockf(fd, F_TLOCK, sz);
if (! status) {
return 0;
} else if (status != EINTR &&
status != EACCES &&
status != EAGAIN) {
return status;
} else {

int twait = 250000, repeat = 0;
while (usleep(twait) && (++repeat) < 100) {
twait -= 1000;


}
if (! ((++tout) % 4)) {
--tsec;
}
}
} while (tsec > 0);
return ETIMEDOUT;
}
_______________________________________________________________


Humm... If your timeout granularity is a second, then this little hack might
just work out fairly well for you after all. What do you think?

Szabolcs Ferenczi

unread,
Feb 28, 2008, 3:47:18 AM2/28/08
to
On Feb 28, 4:02 am, A <ad_...@yahoo.com> wrote:
> On Feb 27, 9:09 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
>
>
>
> > Lets see if I can generate some laughs:
>
> I have seen precisely this in use, that is
>      attempt F_TLOCK
>      sleep a bit
> until timeout

Yes, you often see such attempt from someone who does not understand
concurrent programming. Note that in a well designed system you would
not need any delaying and yielding except for some very special
situations. This is not one of them.

> Yes, I think you are right, there is a race condition in that logic.

How could be a race condition in some logic that is basically not
working? It would not even compile because you use the condvar signal
outside the protection of any mutex. Your mutex is local to
`timeLock', new for each call. It does not protect anything. That is
not the way it should be used. A mutex must always be associated with
the resource it protects. A condition variable must also be associated
with the mutex if you implement conditional critical region.

You also cannot use the condition variable for signalling some event
like you do in your code. It is not designed for that. It is simply
designed to _optimise_ the performance of your conditional critical
region.

You can always check whether you use a condition variable correctly if
you fake the condvar signal by an empty operation and you fake the
condvar wait by a mutex unlock followed by a lock. (Well, for faking a
timed wait, you need some more effort.) If your algorithm works
correctly in that case, you probably use your condition variable as
expected.

> Basically, I am trying to figure out how to break out of a blocking
> call to
>       lockf(fd, F_LOCK)
> and report that to the caller.

If you want to achieve this, you can wrap each and every call to
`lockf' and the control will be in your hands. But in that case you
short-cut the functionality of the `lockf' call.

Best Regards,
Szabolcs

Chris Thomasson

unread,
Feb 28, 2008, 4:50:10 AM2/28/08
to
"Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
news:10855628-1413-4466...@u72g2000hsf.googlegroups.com...

> On Feb 28, 4:02 am, A <ad_...@yahoo.com> wrote:
> > On Feb 27, 9:09 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
> >
> >
> >
> > > Lets see if I can generate some laughs:
> >
> > I have seen precisely this in use, that is
> > attempt F_TLOCK
> > sleep a bit
> > until timeout

> Yes, you often see such attempt from someone who does not understand
> concurrent programming. Note that in a well designed system you would
> not need any delaying and yielding except for some very special
> situations. This is not one of them.


> > Yes, I think you are right, there is a race condition in that logic.

> How could be a race condition in some logic that is basically not
> working?

There is a clear race-condition in the code as-is. Also, the OP does not
join the thread within the scope of the timeLock function.


> It would not even compile because you use the condvar signal
> outside the protection of any mutex.

Are you kidding me? Are you seriously suggesting some code won't compile
because it calls 'pthread_cond_signal()' outside of a critical-section?
Please tell me your trolling!

Just to make sure that any newbie reading this does not get started down the
wrong path: You can signal a condvar outside the protection of a mutex, this
is basic stuff. I would suggest that Szabolcs learn about condvars before
posting anything which deals with them...


[...]

> You also cannot use the condition variable for signaling some event


> like you do in your code.

Complete load of crap!!!:

http://groups.google.com/group/comp.programming.threads/msg/fc1e13463a9ecb43

http://groups.google.com/group/comp.programming.threads/msg/3c017578d62e0524

The OP was misusing the condvar.


> It is not designed for that. It is simply
> designed to _optimise_ the performance of your conditional critical
> region.

[...]

Bullshi%! Would you stop with this garbage already!?

http://groups.google.com/group/comp.programming.threads/msg/d3bf01cb4e3ecae0


You already called David Butenhof a fool for pointing out the facts and
trying to help you learn something. I suspect that your making these
non-sense claims on purpose; am I feeding a troll or what? Please clarify.

:^/

Rainer Weikusat

unread,
Feb 28, 2008, 5:04:26 AM2/28/08
to

Because relying on EINTR for this is an extraordinaty bad idea: Given
sufficiently bad timing, the signal could arrive before the process
has even entered the locking-call, which would then block
forever. That's a 'classical' lost wakeup condition and longjumping
from the handler is the only reliable way (I know of) to implement
such a timeout.

As I not that long ago posted in another group: A signal handler using
longjmp must not interrupt a function which is not async-signal safe,
otherwise, the beahviour is (as of SUS) undefined. 'lockf' is not
specified as being async-signal safe. If it actually is would be a
property of the implementation to be checked before using it in
combination with such a timeout. But fcntl is required to be
async-signal safe, consequently, using fcntl-based locking in
combination with an alarm-based timeout using longjump should be a
safe and portable alternative.

It is usually easy to ensure what exactly a signal handler can
interrupt *in a single-threaded process*, so using longjump in signal
handlers will usually not cause any issues.

Rainer Weikusat

unread,
Feb 28, 2008, 5:12:34 AM2/28/08
to
Szabolcs Ferenczi <szabolcs...@gmail.com> writes:

[...]

> 5. Do not use the condition variable for event signaling but use it to
> indicate a change in the state of the associated shared variables.

Ehh ... that is 'event signalling'. Basically, a condition variable
is nothing more than a mechanism which some thread can use to go to
sleep until woken up because of 'something'. 'Something' may indicate
a change in the state of 'something else' the thread happens to be
interested in. It needs to check if this is the case and go to sleep
again otherwise.

> For event signaling, if you need it, you should use semaphores.

The 'interesting difference' between a semaphore and a condition
variable is that the former has 'a memory': It can be used to inform
another thread about the fact that some condition was true at some
random time in the past. The semaphore will keep this information
until it is 'polled' from it by some other thread.

Chris Thomasson

unread,
Feb 28, 2008, 5:37:55 AM2/28/08
to
"Rainer Weikusat" <rwei...@mssgmbh.com> wrote in message
news:87d4qhl...@fever.mssgmbh.com...

> Szabolcs Ferenczi <szabolcs...@gmail.com> writes:
>
> [...]
>
>> 5. Do not use the condition variable for event signaling but use it to
>> indicate a change in the state of the associated shared variables.
>
> Ehh ... that is 'event signalling'. Basically, a condition variable
> is nothing more than a mechanism which some thread can use to go to
> sleep until woken up because of 'something'. 'Something' may indicate
> a change in the state of 'something else' the thread happens to be
> interested in. It needs to check if this is the case and go to sleep
> again otherwise.

Indeed.


>> For event signaling, if you need it, you should use semaphores.
>
> The 'interesting difference' between a semaphore and a condition
> variable is that the former has 'a memory': It can be used to inform
> another thread about the fact that some condition was true at some
> random time in the past. The semaphore will keep this information
> until it is 'polled' from it by some other thread.

Nit picking here: A condvar has to be used in conjunction with a mutex. The
data in the critical-section protected by said mutex can be analogous to the
"memory" that a semaphore contains, except that is can be so much more
diverse than a simple signal count. Basically, the only real difference
between the two is that you can post to a POSIX semaphore from within a
signal handler. The main point that Szabolcs seems to be missing is that you
can create a semaphore from condition variable, and vise-versa:

<stupid simple pseudo-code sketch>
_______________________________________________________________
struct semaphore {
int state; /* >= 0 */
pthread_mutex_t mtx;
pthread_cond_t cond;
};

void semaphore_post(semaphore* const _this) {
pthread_mutex_lock(&_this->mtx);
++_this->state;
pthread_mutex_unlock(&_this->mtx);
pthread_cond_signal(&_this->cond);
}

void semaphore_wait(semaphore* const _this) {
pthread_mutex_lock(&_this->mtx);
while (! _this->state) {
pthread_cond_wait(&_this->cond, &_this->mtx);
}
--_this->state;
pthread_mutex_unlock(&_this->mtx);
}


/* if you want example of how to create a condition variable
from semaphores check out Alex Terekhovs algorithm in
pthread-win32 library.
*/
_______________________________________________________________


WRT example above, the "memory" you refer to is the 'semaphore::state'
member. However, like I said, you can add a whole lot more to it, which IMO
makes a condvar so much more powerful than a simple semaphore. Personally,
the only time I use POSIX semaphores is when I need to send a signal out of
a sig-handler...

Szabolcs Ferenczi

unread,
Feb 28, 2008, 5:56:36 AM2/28/08
to
On Feb 28, 11:12 am, Rainer Weikusat <rweiku...@mssgmbh.com> wrote:

> Szabolcs Ferenczi <szabolcs.feren...@gmail.com> writes:
>
> [...]
>
> > 5. Do not use the condition variable for event signaling but use it to
> > indicate a change in the state of the associated shared variables.
>
> Ehh ... that is 'event signalling'.

I can help you in that if you are not familiar with the concept. In
concurrent programming it is a terminus technicus, that is why it is
not known to people ignorant to learn about concurrent programming
before they start working with threads. Shortly, if two processes must
synchronize so that one process has to notify the other one about an
event that happened and the other awaits that notification that is
called event signaling.

The most simple tool for it is the semaphore. You can solved the same
with a flag as a shared variable but then you have to manipulate that
flag under the protection of an associated mutex. If you want to
optimize the performance, you can use an additional condition
variable. The condition variable is not part of the logic, however, it
is just a kind of a performance sugar. Altogether it will be much more
complex for this simple job than a semaphore.

> Basically, a condition variable
> is nothing more than a mechanism which some thread can use to go to
> sleep until woken up because of 'something'. 'Something' may indicate
> a change in the state of 'something else' the thread happens to be
> interested in. It needs to check if this is the case and go to sleep
> again otherwise.

Basically a condition variable is nothing more than an optimization
tool. It is used to optimize the performance of the Conditional
Critical Region. The Conditional Critical Region (CCR) is again a
concurrent programming concept. When in multi-threading you work with
mutexes and condition variables, you are working on a primitive form
of CCR.

> > For event signaling, if you need it, you should use semaphores.
>
> The 'interesting difference' between a semaphore and a condition
> variable is that the former has 'a memory': It can be used to inform
> another thread about the fact that some condition was true at some
> random time in the past. The semaphore will keep this information
> until it is 'polled' from it by some other thread.

The interesting difference is rather that the semaphore combines the
mutual exclusion and the notification mechanism. I am afraid you
intermix the counting semaphore with the binary semaphore here.
Perhaps you should ask someone in your environment who has a basic
knowledge in concurrent programming, I am sure he or she can help you
in this.

Rainer Weikusat

unread,
Feb 28, 2008, 6:19:45 AM2/28/08
to
Szabolcs Ferenczi <szabolcs...@gmail.com> writes:
> On Feb 28, 11:12 am, Rainer Weikusat <rweiku...@mssgmbh.com> wrote:
>> Szabolcs Ferenczi <szabolcs.feren...@gmail.com> writes:
>>
>> [...]
>>
>> > 5. Do not use the condition variable for event signaling but use it to
>> > indicate a change in the state of the associated shared variables.
>>
>> Ehh ... that is 'event signalling'.
>
> I can help you in that if you are not familiar with the concept.

If you don't understand something, which you apparently didn't, a wise
course of action would usually be to ask.

> In concurrent programming it is a terminus technicus, that is why it is
> not known to people ignorant to learn about concurrent programming
> before they start working with threads. Shortly, if two processes must
> synchronize so that one process has to notify the other one about an
> event that happened and the other awaits that notification that is
> called event signaling.

'Event signalling' means 'signalling events'. Who could have guessed
that? Besides, 'change in the state of some shared variable' would be
an 'event', which would be 'signalled' to some other thread if a
different thread does 'something' so that the first thread is informed
about the fact that such a change occured.

> The most simple tool for it is the semaphore.

A 'semaphore' is a general mutual-exclusion primitive invented by
E. Dijkstra last century.

[...]


>> The 'interesting difference' between a semaphore and a condition
>> variable is that the former has 'a memory': It can be used to inform
>> another thread about the fact that some condition was true at some
>> random time in the past. The semaphore will keep this information
>> until it is 'polled' from it by some other thread.
>
> The interesting difference is rather that the semaphore combines the
> mutual exclusion and the notification mechanism. I am afraid you
> intermix the counting semaphore with the binary semaphore here.

A 'binary semaphore' is a special case of a 'counting semaphore',
which makes the latter function like a simple, mutual exclusion
mechanism. I obviously wasn't talking about one and you understood
that I wasn't, as evident from your text.

Markus Elfring

unread,
Feb 28, 2008, 8:20:24 AM2/28/08
to
> It is usually easy to ensure what exactly a signal handler can
> interrupt *in a single-threaded process*, so using longjump in signal
> handlers will usually not cause any issues.

sigsetjmp() and siglongjmp() do not belong to the list of async-signal-safe
functions.
I guess that the approach is not guaranteed to work on all platforms.
http://groups.google.de/group/comp.os.linux.development.apps/msg/a94c48f3793d1380

Regards,
Markus

Rainer Weikusat

unread,
Feb 28, 2008, 8:32:20 AM2/28/08
to
Markus Elfring <Markus....@web.de> writes:
>> It is usually easy to ensure what exactly a signal handler can
>> interrupt *in a single-threaded process*, so using longjump in signal
>> handlers will usually not cause any issues.
>
> sigsetjmp() and siglongjmp() do not belong to the list of
> async-signal-safe functions.

In the presence of signals, all functions defined by this
volume of IEEE Std 1003.1-2001 shall behave as defined when
called from or interrupted by a signal-catching function, with
a single exception: when a signal interrupts an unsafe
function and the signal-catching function calls an unsafe
function, the behavior is undefined.
(SUS 2.4.3)

As I wrote in the post you were replying to:



A signal handler using longjmp must not interrupt a function
which is not async-signal safe, otherwise, the beahviour is
(as of SUS) undefined.

F'up2 cup.

A

unread,
Feb 28, 2008, 10:56:03 AM2/28/08
to
On Feb 27, 11:50 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
>
> Humm... If your timeout granularity is a second, then this little hack might
> just work out fairly well for you after all. What do you think?
>

Thanks for the very lively discussion.

Yes, the granularity is in seconds, typical application usages vary
from a few seconds (3 or 5)
to tens of minutes, depending on the particular application using it.

Yes, this hack is useful (and as I said, was being used), but you may
luck out
with competing peer processes, i.e. some other lucky peer may have
gotten
the lock just before you attempt the F_TLOCK next time.

That is the reason I use the solution using sigsetjmp/siglongjmp,
which I think matches
the application requirements nicely (whoever came in earlier gets the
lock next time)
but alas I can not use those calls in a pthreads program.

I think I have a way of managing the race condition you pointed out.

I introduce a function
whoHasLock(int fd);
which returns the pid of who has the lock (-1 if none has it)
and in the timeLock function,

6: if ( ETIMEDOUT == r ) {
7: pthread_cancel(thrLck);

7a: if ( getpid() == whoHasLock(fd) ) { return 0;}

8: return -1;
}


On the other points.

I could add the mutex to the lockStruct_t and pass it to the thrLckFn
and then put the mutex lock / unlock around the pthread_cond_signal
but I'm afraid of another race condition,
what if that thread gets cancelled just before it unlocks the mutex?

The new thread must have terminated by the time timeLock is ready to
return,
do I still need to join with it? even if I cancelled it?

I would use an "elegant" solution if possible, otherwise I'll use
whatever "in-elegant" method that will get me what I need.

Best regards.

Szabolcs Ferenczi

unread,
Feb 28, 2008, 11:14:43 AM2/28/08
to
On Feb 27, 10:11 pm, A <ad_...@yahoo.com> wrote:

> The function timeLock in the OP maybe called by multiple threads as
> long as the fd's
> do not refer to the same file. If they refer to the same file, then
> all get the lock at the same time,
> so second and subsequent calls always timeout.
> This is due to the behaviour of fd's themselves,
> thus, the timeLock function is thread-safe IFF the fd's refer to
> distinct files,
> otherwise calls to it should be serialized.

While a heated discussion is going around, deviating from your
problem, let us peacefully progress towards your expected solution.
Now, if you want to achieve what you outlined above, you probably want
a solution that I have already hinted about (see post on Feb 27, 10:24
pm). I have suggested you to extend the structure so that the shared
resource (`fd') is associated with the tools needed for the
protection, something like this:

typedef struct {
int fd;
pthread_mutex_t m;
pthread_cond_t c;
} lockStruct_t;

Once you have the critical resource and the protecting resources
grouped together, your `timeLock' function can be as simple as this:

int
timeLock(lockStruct_t *lp, int tsecs)
{
int r = 0;
struct timespec t;
if ( 0 > tsecs ) tsecs = 0;
t.tv_nsec = 0;


t.tv_sec = time(NULL) + tsecs;

pthread_mutex_lock(&lp->m);
while (fileLocked(lp->fd) && r == 0)
r = pthread_cond_timedwait(&lp->c, &lp->m, &t);
if (!fileLocked(lp->fd))
lockf(lp->fd, F_LOCK, 0);
pthread_mutex_unlock(&lp->m);


if ( ETIMEDOUT == r )

return -1;
return r;
}

Note that your function `timeLock' gets the structure instance
reference and not only the file descriptor number. For instantiating
and freeing a `lockStruct_t' instance, I recommend you to define
factory functions. Also you can implement the `fileLocked' predicate
accordingly. I am not sure whether the calculation of the time value
is correct, but you can fix that.

Finally, as I suggested earlier, it all works only if you do not use
`lockf' without the wrappers in your code and you implement the
complimentary unlock wrapper as well. It can be something like this:

void
unLock(lockStruct_t *lp)
{
pthread_mutex_lock(&lp->m);
lockf(lp->fd, F_ULOCK, 0);
pthread_cond_broadcast(&lp->c);
pthread_mutex_unlock(&lp->m);
}

Of course you should make this code robust by checking the return
codes but that is not an issue here, I guess. Nevertheless, what you
wanted to achieve, you get it with this solution.

You can also check the sympthoms I was telling about, how the
condition variable plays role only in the optimization but has nothing
to do with the logic of the algorithm. Check out why the while loop is
necessary around the `pthread_cond_timedwait'. All would work if you
just remove `pthread_cond_broadcast' and substitute
`pthread_cond_timedwait' with `pthread_mutex_unlock(&lp-
>m);pthread_mutex_lock(&lp->m);' while extending the condition of the
while loop with `&& t.tv_sec < time(NULL)'. Play with it.

To be exact, this version will also work but not so efficiently:

typedef struct {
int fd;
pthread_mutex_t m;
} lockStruct_t;

void
timeUnLock(lockStruct_t *lp)
{
pthread_mutex_lock(&lp->m);
lockf(lp->fd, F_ULOCK, 0);
pthread_mutex_unlock(&lp->m);
}

int
timeLock(lockStruct_t *lp, int tsecs)
{
int r = 0;
struct timespec t;
if ( 0 > tsecs ) tsecs = 0;
t.tv_nsec = 0;
t.tv_sec = (int)time(NULL) + tsecs;
pthread_mutex_lock(&lp->m);
while (fileLocked(lp->fd) &&
0 == (r = t.tv_sec < time(NULL) ? ETIMEDOUT : 0)) {
pthread_mutex_unlock(&lp->m);
pthread_mutex_lock(&lp->m);
}
if (!fileLocked(lp->fd))
lockf(lp->fd, F_LOCK, 0);
pthread_mutex_unlock(&lp->m);


if ( ETIMEDOUT == r ) {

return -1;
}
return r;
}

As you see, there is no condition variable there because that is only
needed for performance tuning.

If you have any more questions, I am ready to help.

Best Regards,
Szabolcs

David Schwartz

unread,
Feb 28, 2008, 11:43:39 AM2/28/08
to
On Feb 28, 12:47 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:

> How could be a race condition in some logic that is basically not
> working? It would not even compile because you use the condvar signal
> outside the protection of any mutex.

Even if there was anything wrong with this, which there is not, how
would the *compiler* detect it?

> Your mutex is local to
> `timeLock', new for each call. It does not protect anything.

True, but that has nothing to do with his problem. His problem is that
the created thread might call 'pthread_cond_signal' before he gets a
chance to call 'pthread_cond_timedwait', in which case he will be
waiting for something that has already happened.

His problem may be due to a misunderstanding about what
'pthread_cond_timedwait' does. It is not a conditional wait, it is an
unconditional wait *for* a condition.

> That is
> not the way it should be used. A mutex must always be associated with
> the resource it protects. A condition variable must also be associated
> with the mutex if you implement conditional critical region.

True, but not his problem.

> You also cannot use the condition variable for signalling some event
> like you do in your code. It is not designed for that. It is simply
> designed to _optimise_ the performance of your conditional critical
> region.

I have no idea what you could possibly mean by that. If you imagine
that that's helpful to someone who doesn't completely understand
condition variables, you are fooling yourself. Condition variables
don't optimize anything, they're a signaling mechanism.

DS

Szabolcs Ferenczi

unread,
Feb 28, 2008, 12:05:28 PM2/28/08
to
On Feb 28, 5:43 pm, David Schwartz <dav...@webmaster.com> wrote:
> On Feb 28, 12:47 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
> wrote:
>
> > How could be a race condition in some logic that is basically not
> > working? It would not even compile because you use the condvar signal
> > outside the protection of any mutex.
>
> Even if there was anything wrong with this, which there is not, how
> would the *compiler* detect it?

Ok, the C compiler cannot detect it.

> > Your mutex is local to
> > `timeLock', new for each call. It does not protect anything.
>
> True, but that has nothing to do with his problem.

I am afraid, it does. How do you want to achieve mutual exclusion if
your threads are trying to exclude each other on disjoint mutexes?

> His problem is that
> the created thread might call 'pthread_cond_signal' before he gets a
> chance to call 'pthread_cond_timedwait', in which case he will be
> waiting for something that has already happened.

Well, it is basically wrong to use the condition variable for event
signaling. It is not designed for that.

> His problem may be due to a misunderstanding about what
> 'pthread_cond_timedwait' does. It is not a conditional wait, it is an
> unconditional wait *for* a condition.

I am afraid there is even more misunderstanding here. It is not even a
wait, it is just a performance tuning trick. The wait happens in an
optimized busy loop, see the while loop.

> > That is
> > not the way it should be used. A mutex must always be associated with
> > the resource it protects. A condition variable must also be associated
> > with the mutex if you implement conditional critical region.

> I have no idea what you could possibly mean by that. ...


> Condition variables
> don't optimize anything, they're a signaling mechanism.

It is not only your fault that you have no idea about it. I can see
that many people new to concurrent programming having problem with it.
That is why I show it by an example. Perhaps this will help you too:

http://groups.google.com/group/comp.programming.threads/msg/c197e52dcfded226

If you have any more questions, I am ready to help you.

Best Regards,
Szabolcs

Sergei Organov

unread,
Feb 28, 2008, 12:46:03 PM2/28/08
to
Szabolcs Ferenczi <szabolcs...@gmail.com> writes:

> On Feb 28, 5:43 pm, David Schwartz <dav...@webmaster.com> wrote:
>> On Feb 28, 12:47 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>

[...]


>> > That is
>> > not the way it should be used. A mutex must always be associated with
>> > the resource it protects. A condition variable must also be associated
>> > with the mutex if you implement conditional critical region.
>
>> I have no idea what you could possibly mean by that. ... Condition
>> variables don't optimize anything, they're a signaling mechanism.
>
> It is not only your fault that you have no idea about it. I can see
> that many people new to concurrent programming having problem with it.

The question is if anybody else but you shares your idea about condition
variables?

> That is why I show it by an example. Perhaps this will help you too:
>
> http://groups.google.com/group/comp.programming.threads/msg/c197e52dcfded226

No, this doesn't help as it's your own idea once again.

> If you have any more questions, I am ready to help you.

Care to give us a reference that doesn't refer to your own opinion?

-- Sergei.

A

unread,
Feb 28, 2008, 1:10:04 PM2/28/08
to
On Feb 28, 11:14 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:

Thanks for your message and your code example.

I am assuming that fileLocked(lp->fd) a function which returns true if
there is a lock on the fd, right?

Now, I have a few questions.

First,


> while (fileLocked(lp->fd) && r == 0)
> r = pthread_cond_timedwait(&lp->c, &lp->m, &t);

Suppose a peer process has the lock, I enter the .._timedwait with a
timeout of 30sec
and after 2 seconds, the peer has released the lock.
I still keep waiting for the next 28 seconds because no one wakes me
up
(and in the meantime another peer process might come up and acquire
the lock)

Also, isn't there a race situation in the segment


> if (!fileLocked(lp->fd))
> lockf(lp->fd, F_LOCK, 0);

That is, the if (...) is true, but before the lockf(...) is executed,
a peer process gets the lock
and then I'm stuck in the system call and I have no way of breaking
out of it.

Best regards

Rainer Weikusat

unread,
Feb 28, 2008, 2:10:25 PM2/28/08
to
"Chris Thomasson" <cri...@comcast.net> writes:
> "Rainer Weikusat" <rwei...@mssgmbh.com> wrote in message

[...]

>> The 'interesting difference' between a semaphore and a condition
>> variable is that the former has 'a memory': It can be used to inform
>> another thread about the fact that some condition was true at some
>> random time in the past. The semaphore will keep this information
>> until it is 'polled' from it by some other thread.
>
> Nit picking here: A condvar has to be used in conjunction with a
> mutex. The data in the critical-section protected by said mutex can be
> analogous to the "memory" that a semaphore contains, except that is
> can be so much more diverse than a simple signal count.

The 'simple signal count' is nevertheless useful in situations where
the fact that some condition became true at some unspecified point in
the past needs to be communicated from one thread to another. A
counting semaphore can obviously be implemented using a counter, a
mutex and a condition variable, but if the semantics of a semaphore
are exactly what is needed (eg to store the number of currently available
data items in a ring buffer, with some set of threads competing
[interlocked with each other] for these data items and some other set
of threads inserting them [interlocked with each other]), why
reimplement it?

Szabolcs Ferenczi

unread,
Feb 28, 2008, 2:11:01 PM2/28/08
to
On Feb 28, 7:10 pm, A <ad_...@yahoo.com> wrote:
...

> Now, I have a few questions.
>
> First,
>
> >    while (fileLocked(lp->fd) && r == 0)
> >       r = pthread_cond_timedwait(&lp->c, &lp->m, &t);
>
> Suppose a peer process has the lock, I enter the .._timedwait with a
> timeout of 30sec
> and after 2 seconds, the peer has released the lock.
> I still keep waiting for the next 28 seconds because no one wakes me
> up
> (and in the meantime another peer process might come up and acquire
> the lock)

Which lock are we talking about? There is a mutex lock and there is a
file lock?

If your peer process has the file lock and in the meantime you attempt
a `timeLock' for the same file that means that you will end up in
the .._timedwait as you said. When your peer releases the file lock,
it must do that via the wrapper `unLock' function and that means that
there is a signal coming for the condition variable and that makes the
`pthread_cond_timedwait' return with zero. When it returns it makes
sure that you will have the mutex lock. Then you check the conditions
of the while loop and you will find that the file is not locked any
more, so you can proceed and lock it while still inside the critical
region. So, if it happens after 2 seconds, you will have the chance to
lock the file long before the timer out.

Does that answer your question?

> Also, isn't there a race situation in the segment
>      >    if (!fileLocked(lp->fd))
>      >      lockf(lp->fd, F_LOCK, 0);
>
> That is, the if (...) is true, but before the lockf(...) is executed,
> a peer process gets the lock
> and then I'm stuck in the system call and I have no way of breaking
> out of it.

It is still inside the critical region, the lock is held, so it is
guaranteed that there can only one process stay there. There cannot be
any other process sneaking in between the two file operations. Well,
if all the `lockf' operations are wrapped as I have suggested.

Best Regards,
Szabolcs

A

unread,
Feb 28, 2008, 3:31:53 PM2/28/08
to
On Feb 28, 2:11 pm, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:
>

> It is still inside the critical region, the lock is held, so it is
> guaranteed that there can only one process stay there. There cannot be
> any other process sneaking in between the two file operations. Well,
> if all the `lockf' operations are wrapped as I have suggested.
>

No, that is not the situation and is not applicable in my case.

Here is the situation.

There are a bunch of programs, some in C, some in Perl,
which compete to acquire a lock on a file.
Each process will attempt to acquire a lock,
given a finite (but different) timeout (granularity of seconds).

When a process releases the lock on the file,
either using fcntl call or closing the file or terminating,
one of the other waiting processes gets the lock,
preferably the process which requested the lock earliest.
[ this is the point I was making while responding to Chris's mail
above
the sleep-a-while try F_TLOCK will work but I may luck out]

A process may timeout waiting for the lock and go away from the scene.

That is all.
There is no other constraint, no other shared memory or file or
semaphore
or whatever between these processes.

If I need to develop a new program, I can do that in Perl or
unthreaded C
and all programs behave as expected.

Now I need program using pthreads to work with these programs in the
same way.
Changing the other programs is not an option.

Best regards.

Markus Elfring

unread,
Feb 28, 2008, 3:50:32 PM2/28/08
to
> There are a bunch of programs, some in C, some in Perl,
> which compete to acquire a lock on a file.

This smells for me that a (distributed) lock sever might be needed for your
application architecture.

Regards,
Markus

David Schwartz

unread,
Feb 28, 2008, 5:14:07 PM2/28/08
to

Szabolcs Ferenczi wrote:

> On Feb 28, 5:43 pm, David Schwartz <dav...@webmaster.com> wrote:
> > On Feb 28, 12:47 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
> > wrote:

> > > Your mutex is local to
> > > `timeLock', new for each call. It does not protect anything.

> > True, but that has nothing to do with his problem.

> I am afraid, it does. How do you want to achieve mutual exclusion if
> your threads are trying to exclude each other on disjoint mutexes?

He doesn't want or need mutual exclusion, just event-like
synchronization. He only needs mutual exclusion where the
implementation details of his synchronization mechanism require it.

> > His problem is that
> > the created thread might call 'pthread_cond_signal' before he gets a
> > chance to call 'pthread_cond_timedwait', in which case he will be
> > waiting for something that has already happened.

> Well, it is basically wrong to use the condition variable for event
> signaling. It is not designed for that.

Then what do you think it is designed for? In fact, signaling an event
is the primary use of condition variables.

> > His problem may be due to a misunderstanding about what
> > 'pthread_cond_timedwait' does. It is not a conditional wait, it is an
> > unconditional wait *for* a condition.

> I am afraid there is even more misunderstanding here. It is not even a
> wait, it is just a performance tuning trick. The wait happens in an
> optimized busy loop, see the while loop.

You are babbling nonsense. The 'pthread_cond_timedwait' function is an
unconditional wait for a condition.

> > > That is
> > > not the way it should be used. A mutex must always be associated with
> > > the resource it protects. A condition variable must also be associated
> > > with the mutex if you implement conditional critical region.

> > I have no idea what you could possibly mean by that. ...
> > Condition variables
> > don't optimize anything, they're a signaling mechanism.

> It is not only your fault that you have no idea about it. I can see
> that many people new to concurrent programming having problem with it.
> That is why I show it by an example. Perhaps this will help you too:

Everyone is wrong but you? Even the people who wrote the libraries,
participated in the standardization processes, and have been writing
multi-threaded programs for collectively about a hundred years? Isn't
it much more likely that it is you who are confused?

> http://groups.google.com/group/comp.programming.threads/msg/c197e52dcfded226

>>void
>>unLock(lockStruct_t *lp)
>>{
>> pthread_mutex_lock(&lp->m);
>> lockf(lp->fd, F_ULOCK, 0);
>> pthread_cond_broadcast(&lp->c);
>> pthread_mutex_unlock(&lp->m);
>>}

This is clumsy and ugly code. What shared data do you think the mutex
is protecting here?

> If you have any more questions, I am ready to help you.

No thanks.

DS

Szabolcs Ferenczi

unread,
Feb 28, 2008, 5:41:17 PM2/28/08
to
On Feb 28, 11:14 pm, David Schwartz <dav...@webmaster.com> wrote:

> Everyone is wrong but you? Even the people who wrote the libraries,
> participated in the standardization processes, and have been writing
> multi-threaded programs for collectively about a hundred years? Isn't
> it much more likely that it is you who are confused?

Let me make a humble note that if you make a giant lie, it will not be
true. I have a strong feeling that you are not writing multi-threaded
programs for hundred years either individually nor collectively.
Should I explain to you why is it impossible?

Peace,
Szabolcs

Chris Friesen

unread,
Feb 28, 2008, 5:49:02 PM2/28/08
to
Szabolcs Ferenczi wrote:
> I have a strong feeling that you are not writing multi-threaded
> programs for hundred years either individually nor collectively.
> Should I explain to you why is it impossible?

It is hard to take you seriously when you make statements like this.

Pthreads have been around for a dozen years, and the concept of threads
is much older than that. It doesn't take too many people to get more
than 100 years of collective experience.

Chris

David Schwartz

unread,
Feb 28, 2008, 5:57:11 PM2/28/08
to
On Feb 28, 2:41 pm, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:

> On Feb 28, 11:14 pm, David Schwartz <dav...@webmaster.com> wrote:

> > Everyone is wrong but you? Even the people who wrote the libraries,
> > participated in the standardization processes, and have been writing
> > multi-threaded programs for collectively about a hundred years? Isn't
> > it much more likely that it is you who are confused?

> Let me make a humble note that if you make a giant lie, it will not be
> true.

Right, there's a huge conspiracy out there to lie to people about
condition variables.

> I have a strong feeling that you are not writing multi-threaded
> programs for hundred years either individually nor collectively.
> Should I explain to you why is it impossible?

Please, I'd like to hear why that's impossible. (A hundred years
individually does seem impossible, I certainly will agree to that.)

DS

Szabolcs Ferenczi

unread,
Feb 28, 2008, 5:57:19 PM2/28/08
to

Well, I just forgot to add that I might be wrong.

Best Regards,
Szabolcs

Message has been deleted

Chris Thomasson

unread,
Feb 28, 2008, 8:18:10 PM2/28/08
to

"Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
news:1e9dc7a8-426b-42e2...@72g2000hsu.googlegroups.com...
[...]

> It is not only your fault that you have no idea about it. I can see
> that many people new to concurrent programming having problem with it.
> That is why I show it by an example. Perhaps this will help you too:
>
> http://groups.google.com/group/comp.programming.threads/msg/c197e52dcfded226
>
> If you have any more questions, I am ready to help you.

I think you have a bug. Lets see here...

_______________________________________________________________


int
timeLock(lockStruct_t *lp, int tsecs)
{
int r = 0;
struct timespec t;
if ( 0 > tsecs ) tsecs = 0;
t.tv_nsec = 0;
t.tv_sec = time(NULL) + tsecs;
pthread_mutex_lock(&lp->m);

while (fileLocked(lp->fd) && r == 0)
r = pthread_cond_timedwait(&lp->c, &lp->m, &t);

/* okay lets say you get here and r == ETIMEDOUT,
and the file is not locked. This is legitimate
condition right here...
*/


if (!fileLocked(lp->fd))
lockf(lp->fd, F_LOCK, 0);

/* since the file is not locked, you lock it */

pthread_mutex_unlock(&lp->m);
if ( ETIMEDOUT == r )

/* now you return failure, when you should of
had success! Crap. */

return -1;
return r;

}
_______________________________________________________________

BTW why do you broadcast? Only one thread can take the lock. You only need
to signal.

Chris Thomasson

unread,
Feb 28, 2008, 9:22:07 PM2/28/08
to

"A" <ad_...@yahoo.com> wrote in message
news:2d56d2b6-1a64-4748...@u69g2000hse.googlegroups.com...

On Feb 27, 11:50 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
> >
> > Humm... If your timeout granularity is a second, then this little hack
> > might
> > just work out fairly well for you after all. What do you think?
> >

> Thanks for the very lively discussion.

> Yes, the granularity is in seconds, typical application usages vary
> from a few seconds (3 or 5)
> to tens of minutes, depending on the particular application using it.

Is wrapping the file-descriptor in another struct okay? From the look of
your API, it seems that your not wrapping the descriptor because you pass it
in as an 'int'. Where are you getting that 'int' from? What's does the
data-structure which holds it look like? You could decrease the generality
of the API by passing it a pointer to that structure and use something like
what Szabolcs suggested (he had a bug in his example code; I pointed it
out). But then you are going to need to funnel all calls to 'lockf()'
through he wrapper API. It looks like you want to make this as generic as
possible. You could use the method that David Schwartz briefly outlined. Or,
you could make a tweak to the naive method I posted. You could do it all in
a single thread and use producer/consumer pattern. You want some
pseudo-code?

Chris Thomasson

unread,
Feb 28, 2008, 11:52:34 PM2/28/08
to
"Chris Thomasson" <cri...@comcast.net> wrote in message
news:FcqdnZSQYoS3xlra...@comcast.com...

>
> "Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
> news:1e9dc7a8-426b-42e2...@72g2000hsu.googlegroups.com...
> [...]
>
>> It is not only your fault that you have no idea about it. I can see
>> that many people new to concurrent programming having problem with it.
>> That is why I show it by an example. Perhaps this will help you too:
>>
>> http://groups.google.com/group/comp.programming.threads/msg/c197e52dcfded226
>>
>> If you have any more questions, I am ready to help you.
[...]

> BTW why do you broadcast? Only one thread can take the lock. You only need
> to signal.

I say this because your locking at the exact same offset.

Chris Thomasson

unread,
Feb 28, 2008, 11:57:08 PM2/28/08
to

"Chris Thomasson" <cri...@comcast.net> wrote in message
news:ToGdnXwwL-E2HFva...@comcast.com...

> "Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
> news:10855628-1413-4466...@u72g2000hsf.googlegroups.com...
[...]

>> It would not even compile because you use the condvar signal
>> outside the protection of any mutex.
>
> Are you kidding me? Are you seriously suggesting some code won't compile
> because it calls 'pthread_cond_signal()' outside of a critical-section?
> Please tell me your trolling!
>
> Just to make sure that any newbie reading this does not get started down
> the wrong path: You can signal a condvar outside the protection of a
> mutex, this is basic stuff. I would suggest that Szabolcs learn about
> condvars before posting anything which deals with them...
[...]

To clarify, you can signal/broadcast outside the protection of the mutex
when you make a prior state shift that warrants wakeup(s). You take the
lock; swing the protected state into something that is analogous to an
event; unlock; and do a signal if only one thread out of many needs to wake,
or do a broadcast if you need to signal a specific thread, or more than one.
You need to broadcast if you need to wake a specific thread because you
cannot direct the signals to any one thread in particular.

Chris Thomasson

unread,
Feb 29, 2008, 12:06:52 AM2/29/08
to

"Szabolcs Ferenczi" <szabolcs...@gmail.com> wrote in message
news:23f215c8-d1f2-4a1b...@c33g2000hsd.googlegroups.com...

> On Feb 28, 11:49 pm, Chris Friesen <cbf...@mail.usask.ca> wrote:
> > Szabolcs Ferenczi wrote:
> > > I have a strong feeling that you are not writing multi-threaded
> > > programs for hundred years either individually nor collectively.
> > > Should I explain to you why is it impossible?
> v>

> > It is hard to take you seriously when you make statements like this.
> >
> > Pthreads have been around for a dozen years, and the concept of threads
> > is much older than that. It doesn't take too many people to get more
> > than 100 years of collective experience.
> >
> > Chris

> Well, I just forgot to add that I might be wrong.

Indeed.

Szabolcs Ferenczi

unread,
Feb 29, 2008, 6:06:08 AM2/29/08
to

If that is the situation what you describe above, I strongly advise
you to revisit the post of William Ahern who describes it to you how
to solve your problem with an alarm thread:

http://groups.google.com/group/comp.programming.threads/msg/a8818c7701cbd8b4

If you need some help how to implement an alarm thread with pthreads,
I can help you in that as well if you like.

However, I still claim that if you need any delay or timeout in a
concurrent program that is a design smell in most cases.

Best Regards,
Szabolcs

A

unread,
Feb 29, 2008, 11:55:16 AM2/29/08
to
On Feb 28, 9:22 pm, "Chris Thomasson" <cris...@comcast.net> wrote:
>
> Is wrapping the file-descriptor in another struct okay? From the look of
> your API, it seems that your not wrapping the descriptor because you pass it
> in as an 'int'. Where are you getting that 'int' from? What's does the
> data-structure which holds it look like? You could decrease the generality
> of the API by passing it a pointer to that structure and use something like
> what Szabolcs suggested (he had a bug in his example code; I pointed it
> out). But then you are going to need to funnel all calls to 'lockf()'
> through he wrapper API. It looks like you want to make this as generic as
> possible. You could use the method that David Schwartz briefly outlined. Or,
> you could make a tweak to the naive method I posted. You could do it all in
> a single thread and use producer/consumer pattern. You want some
> pseudo-code?

Yes, wrapping the fd in another struct would be okay, that is,
we will be providing a new API to the end user, as long as
it is similar to and compatible with the other API.

Right now, the user applications obtain a file name from their users
(or their own
configuration), then they simply do an open(2) and use that fd.

Yes, I am trying to make it as generic, or rather as simple, as
possible;
that is the programmers who use this library should be able to use
it with minimum impact.

Please note that the new pthreads program should be able to compete
fairly for the file lock resource with old legacy programs.

I am trying to understand how to implement the method David Schwartz
described.

Yes, doing it without spawning a new thread would be definitely better
and I would greatly appreciate pseudo-code.

Best regards.

A

unread,
Feb 29, 2008, 12:06:26 PM2/29/08
to
On Feb 29, 6:06 am, Szabolcs Ferenczi <szabolcs.feren...@gmail.com>
wrote:
>

> If that is the situation what you describe above, I strongly advise
> you to revisit the post of William Ahern who describes it to you how
> to solve your problem with an alarm thread:
>
> http://groups.google.com/group/comp.programming.threads/msg/a8818c770...

>
> If you need some help how to implement an alarm thread with pthreads,
> I can help you in that as well if you like.
>
> However, I still claim that if you need any delay or timeout in a
> concurrent program that is a design smell in most cases.
>
> Best Regards,
> Szabolcs

Thanks for your detailed posts and for pointing out William Ahern's.
I hear your concern for the main design, but at least here, the
main concern is inter-operability with the legacy programs.

I think I understand the basics of Ahern's logic, that is it also
uses an auxiliary thread to set up the alarm and interrupt the flock.

Now, if I restrict my users to serialize their calls to timeLock
then one additional timer thread would work.
If the end users have in principle, the potential of calling
the timeLock from multiple threads (targetting different files)
then a timer thread would be needed for each call.

Best regards.

Markus Elfring

unread,
Feb 29, 2008, 3:15:35 PM2/29/08
to
> Right now, the user applications obtain a file name from their users
> (or their own configuration), then they simply do an open(2) and use that fd.
>
> Yes, I am trying to make it as generic, or rather as simple, as possible;
> that is the programmers who use this library should be able to use
> it with minimum impact.

Would you like to encapsulate your specific locking and timer functionality with
a customised file system interface?
Are there any more designs on the way for your server implementation?
http://en.wikipedia.org/wiki/Distributed_lock_manager
http://www.cs.duke.edu/~chase/cps212-f00/lab2.htm
http://www.freepatentsonline.com/6173293.html

Regards,
Markus

0 new messages