Is "assert I'm holding this mutex locked" Feasible? - c

In The Tools We Work With the author of software Varnish expressed his disappointment to the new ISO C standard draft. Especially he thinks there should be something useful like "assert I'm holding this mutex locked" function, and he claims he wrote one in Vanish.
I checked code. It essentially like this:
struct ilck {
unsigned magic;
pthread_mutex_t mtx;
int held;
pthread_t owner;
VTAILQ_ENTRY(ilck) list;
const char *w;
struct VSC_C_lck *stat;
};
void Lck__Lock(struct ilck *ilck, const char *p, const char *f, int l)
{
if (!(params->diag_bitmap & 0x18)) {
AZ(pthread_mutex_lock(&ilck->mtx));
AZ(ilck->held);
ilck->stat->locks++;
ilck->owner = pthread_self();
ilck->held = 1;
return;
}
r = pthread_mutex_trylock(&ilck->mtx);
assert(r == 0 || r == EBUSY);
if (r) {
ilck->stat->colls++;
if (params->diag_bitmap & 0x8)
VSL(SLT_Debug, 0, "MTX_CONTEST(%s,%s,%d,%s)",
p, f, l, ilck->w);
AZ(pthread_mutex_lock(&ilck->mtx));
} else if (params->diag_bitmap & 0x8) {
VSL(SLT_Debug, 0, "MTX_LOCK(%s,%s,%d,%s)", p, f, l, ilck->w);
}
ilck->stat->locks++;
ilck->owner = pthread_self();
ilck->held = 1;
}
void
Lck__Assert(const struct ilck *ilck, int held)
{
if (held)
assert(ilck->held &&
pthread_equal(ilck->owner, pthread_self()));
else
assert(!ilck->held ||
!pthread_equal(ilck->owner, pthread_self()));
}
I omit the implementation of the try-lock and unlock operation since they are basically routine. The place where I have question is the Lck__Assert(), in which the access to ilck->held and lick->owner is not protected by any mutex.
So say the following sequence of event:
Thread A locks a mutex.
Thread A unlocks it.
Thread B locks the same mutex. In the course of locking (within
Lck_lock()), thread B is preempted after it updates ilck->held but
before it updates ilck->owner. That should be possible because of
the optimizer and CPU out-of-order.
Thread A runs and invoke the Lck__Assert(), the assertion will be
true and thread A in fact doesn't hold the mutex.
In my opinion there should be some "global" mutex to protect the mutex's its own data, or at least some write/read barrier. Is my analysis correct?

I have contacted the author. He says my analysis is valid and using a memset(,0,) to unset the "thread_t owner" as thread_t is not a transparent struct with specified assignment operator. Hope that works on most platforms.

Related

Can I check a pthread_t to see if it was initialized by pthread_create, because pthread_join segfaults if pthread_t has not been initialized [duplicate]

I would like to call pthread_join for a given thread id, but only if that thread has been started. The safe solution might be to add a variable to track which thread where started or not. However, I wonder if checking pthread_t variables is possible, something like the following code.
pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;
/* thread 1 and 2 are strated or not depending on various condition */
....
/* cleanup */
if(thr1 != some_invalid_value)
pthread_join(&thr1);
if(thr2 != some_invalid_value)
pthread_join(&thr2);
Where some_invalid_value could be 0, or an implementation dependant 'PTHREAD_INVALID_ID' macro
PS :
My assumption is that pthread_t types are comparable and assignable, assumption based on
PPS :
I wanted to do this, because I thought calling pthread_join on invalid thread id was undefinde behaviour. It is not. However, joining a previously joined thread IS undefined behaviour. Now let's assume the above "function" is called repeatedly.
Unconditionnally calling pthread_join and checking the result might result in calling pthread_join on a previously joined thread.
Your assumption is incorrect to start with. pthread_t objects are opaque. You cannot compare pthread_t types directly in C. You should use pthread_equal instead.
Another consideration is that if pthread_create fails, the contents of your pthread_t will be undefined. It may not be set to your invalid value any more.
My preference is to keep the return values of the pthread_create calls (along with the thread IDs) and use that to determine whether each thread was started correctly.
As suggested by Tony, you can use pthread_self() in this situation.
But do not compare thread_ts using == or !=. Use pthread_equal.
From the pthread_self man page:
Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.
I recently ran into this same issue. If pthread_create() failed, I ended up with a undefined, invalid value stored in my phtread_t structure. As a result, I keep a boolean associated with each thread that gets set to true if pthread_create() succeeded.
Then all I need to do is:
void* status;
if (my_thread_running) {
pthread_join(thread, &status);
my_thread_running = false;
}
Unfortunately, on systems where pthread_t is a pointer, pthread_equal() can return equality even though the two args refer to different threads, e.g. a thread can exit and a new thread can be created with the same pthread_t pointer value.
I was porting some code that used pthreads into a C++ application, and I had the same question. I decided it was easier to switch to the C++ std::thread object, which has the .joinable() method to decide whether or not to join, i.e.
if (t.joinable()) t.join();
I found that just calling pthead_join on a bad pthread_t value (as a result of pthread_create failing) caused a seg fault, not just an error return value.
Our issue was that we couldn't know if a pthread had been started or not, so we make it a pointer and allocate/de-allocate it and set it to NULL when not in use:
To start:
pthread_t *pth = NULL;
pth = malloc(sizeof(pthread_t));
int ret = pthread_create(pth, NULL, mythread, NULL);
if( ret != 0 )
{
free(pth);
pth = NULL;
}
And later when we need to join, whether or not the thread was started:
if (pth != NULL)
{
pthread_join(*pth, NULL);
free(pth);
pth = NULL;
}
If you need to respawn threads quickly then the malloc/free cycle is undesirable, but it works for simple cases like ours.
This is an excellent question that I really wish would get more discussion in C++ classes and code tests.
One option for some systems-- which may seem like overkill to you, but has come in handy for me-- is to start a thread which does nothing other than efficiently wait for a tear-down signal, then quit. This thread stays running for the life of the application, going down very late in the shutdown sequence. Until that point, the ID of this thread can effectively be used as an "invalid thread" value-- or, more likely, as an "uninitialized" sentinel-- for most purposes. For example, my debug libraries typically track the threads from which mutexes were locked. This requires initialization of that tracking value to something sensible. Because POSIX rather stupidly declined to require that platforms define an INVALID_THREAD_ID, and because my libraries allow main() to lock things (making the pthread_self checks that are a good solution pthread_create unusable for lock tracking), this is the solution I have come to use. It works on any platform.
Note, however, that you have a little more design work to do if you want this to be able to initialize static thread references to invalid values.
For C++ (not really sure what language the OP was asking about) another simple option (but I think this one is still the simplest as long as you don't need to treat pthread_self() as valid anywhere) would be to use std::optional<pthread_t> (or boost's version if you can't swing C++17 or later, or implement something similar yourself).
Then use .has_value() to check if values are valid, and be happy:
// so for example:
std::optional<pthread_t> create_thread (...) {
pthread_t thread;
if (pthread_create(&thread, ...))
return std::optional<pthread_t>();
else
return thread;
}
// then:
std::optional<pthread_t> id = create_thread(...);
if (id.has_value()) {
pthread_join(id.value(), ...);
} else {
...;
}
You still need to use pthread_equal when comparing valid values, so all the same caveats apply. However, you can reliably compare any value to an invalid value, so stuff like this will be fine:
// the default constructed optional has no value
const std::optional<pthread_t> InvalidID;
pthread_t id1 = /* from somewhere, no concept of 'invalid'. */;
std::optional<pthread_t> id2 = /* from somewhere. */;
// all of these will still work:
if (id1 == InvalidID) { } // ok: always false
if (id1 != InvalidID) { } // ok: always true
if (id2 == InvalidID) { } // ok: true if invalid, false if not.
if (id2 != InvalidID) { } // ok: true if valud, false if not.
Btw, if you also want to give yourself some proper comparison operators, though, or if you want to make a drop-in replacement for a pthread_t (where you don't have to call .value()), you'll have to write your own little wrapper class to handle all the implicit conversions. It's pretty straightforward, but also getting off-topic, so I'll just drop some code here and give info in the comments if anybody asks. Here are 3 options depending on how old of a C++ you want to support. They provide implicit conversion to/from pthread_t (can't do pthread_t* though), so code changes should be minimal:
//-----------------------------------------------------------
// This first one is C++20 only:
#include <optional>
struct thread_id {
thread_id () =default;
thread_id (const pthread_t &t) : t_(t) { }
operator pthread_t () const { return value(); }
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const pthread_t &L, const thread_id &R) { return thread_id(L) == R; }
bool valid () const { return t_.has_value(); }
void reset () { t_.reset(); }
pthread_t value () const { return t_.value(); } // throws std::bad_optional_access if !valid()
private:
std::optional<pthread_t> t_;
};
//-----------------------------------------------------------
// This works for C++17 and C++20. Adds a few more operator
// overloads that aren't needed any more in C++20:
#include <optional>
struct thread_id {
// construction / conversion
thread_id () =default;
thread_id (const pthread_t &t) : t_(t) { }
operator pthread_t () const { return value(); }
// comparisons
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const thread_id &L, const pthread_t &R) {return L==thread_id(R);}
friend bool operator == (const pthread_t &L, const thread_id &R) {return thread_id(L)==R;}
friend bool operator != (const thread_id &L, const thread_id &R) {return !(L==R);}
friend bool operator != (const thread_id &L, const pthread_t &R) {return L!=thread_id(R);}
friend bool operator != (const pthread_t &L, const thread_id &R) {return thread_id(L)!=R;}
// value access
bool valid () const { return t_.has_value(); }
void reset () { t_.reset(); }
pthread_t value () const { return t_.value(); } // throws std::bad_optional_access if !valid()
private:
std::optional<pthread_t> t_;
};
//-----------------------------------------------------------
// This works for C++11, 14, 17, and 20. It replaces
// std::optional with a flag and a custom exception.
struct bad_pthread_access : public std::runtime_error {
bad_pthread_access () : std::runtime_error("value() called, but !valid()") { }
};
struct thread_id {
thread_id () : valid_(false) { }
thread_id (const pthread_t &t) : thr_(t), valid_(true) { }
operator pthread_t () const { return value(); }
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const thread_id &L, const pthread_t &R) { return L==thread_id(R); }
friend bool operator == (const pthread_t &L, const thread_id &R) { return thread_id(L)==R; }
friend bool operator != (const thread_id &L, const thread_id &R) { return !(L==R); }
friend bool operator != (const thread_id &L, const pthread_t &R) { return L!=thread_id(R); }
friend bool operator != (const pthread_t &L, const thread_id &R) { return thread_id(L)!=R; }
bool valid () const { return valid_; }
void reset () { valid_ = false; }
pthread_t value () const { // throws bad_pthread_access if !valid()
if (!valid_) throw bad_pthread_access();
return thr_;
}
private:
pthread_t thr_;
bool valid_;
};
//------------------------------------------------------
/* some random notes:
- `std::optional` doesn't let you specify custom comparison
functions, which would be convenient here.
- You can't write `bool operator == (pthread_t, pthread_t)`
overloads, because they'll conflict with default operators
on systems where `pthread_t` is a primitive type.
- You have to write overloads for all the combos of
pthread_t/thread_id in <= C++17, otherwise resolution is
ambiguous with the implicit conversions.
- *Really* sloppy but thorough test: https://godbolt.org/z/GY639ovzd

pthread_mutex_init result in Segmentation Fault

I'm a college student learning how to deal with threads and databases.
Overall, I'm trying to make a function that will take a list of locks, see if the current lock the program is handling is in the list, and mutex lock that lock.
Currently, I am having issues initializing the *locks, but every time I do so, I get a segmentation error (core dump).
I already try using the different ways of initializing the mutex lock:
&locks->lock = PTHREAD_MUTEX_INITIALIZER;
as well as using : pthread_mutex_init(&locks->lock, NULL);
on the .h file, it contains
typedef struct {
char *table;
pthrad_mutex_t lock;} TableLock;
main file:
static pthread_mutex_t lock_on_locks;
static int active_tables = 0;
static TableLock *locks = NULL;
// Table locking functions
void sudba_lock(char *table) {
sleep(2);
if (locks == NULL) {
my_realloc(locks, sizeof(TableLock));
}
pthread_mutex_lock(&lock_on_locks);
char table_name[strlen(table) + 1];
table_name[strlen(table)] = '\0';
sprintf(table_name, "%s", table);
if (active_tables == 0) {
pthread_mutex_init(&locks->lock, NULL);
pthread_mutex_lock(&locks->lock);
locks[active_tables].table = table_name;
active_tables++;
}
the my_realloc function is this:
void *my_realloc(void *ptr, size_t size) {
void *result = malloc(size);
if(!result) abort();
return result
}
Any help is appreciated
Your crash has nothing to do with pthread_mutex_lock; it's just that you're passing a null pointer to it because you didn't save the result of realloc. Where you have:
my_realloc(locks, sizeof(TableLock));
it should be:
locks = my_realloc(locks, sizeof(TableLock));
But I'm not clear why you're allocating it anyway since this looks like a single-instance lock. Normally locks either have static storage duration or exist inside some structure you're allocating (whose contents they'll protect). Allocating an individual lock by itself is a code smell.
There are a lot of other things that look wrong with your code too, independent of the crash.

Pthreads and shared memory in C

Can anyone tell me why my shared memory data structure (implemented using sys/shm.h) is not being read correctly by pthreads? This is an edited version of my question, with a reduced amount of code. Hopefully its easier to navigate.
Initially, the structure being referenced is created in shared memory space, so two different applications can read and write to it. The aim: to have one application update the shared structure, and the other read it using pthreads. So far everything things are working to an extent. Both applications can read and write to the shared memory, except the pthreads. they don't seem to pick up the modified shared structure?
An overview of the code is below. It is based on a basic runtime system, however, it is not overly complicated. The function executed within the pthreads is:
void* do_work(void *p)
The shared structure is:
typedef struct WL_CTRL_T
Currently all i am trying do is print out the elements of the array. Initially all elements are set to true. Halfway through the execution, using GDB to halt the process, i update the structure from outside, using the other application, by changing elements 0 and 1 to false, then continue to the process. At this i also print out the state of the array from each application via the sequential code, and the print out is correct. However, when the threads are set off, they print the original state of the array, all true...
The structure contains an array of structs, where the active bool field is read by the pthread
I have tried many ways to try and correct this problem, but no joy.
Any advice appreciated, thanks :-)
/*controller api.h*/
typedef struct WL_CTRL_T
{
int targetNumThreads;
int sizeBuf;
int numEntries;
int nextIdx;
thread_state_control_t volatile thread_state_control[THREAD_NUM];
mon_entry_t buffer[];
} wl_ctrl_t;
typedef struct THREADPOOL_T
{
int num_threads;
int qsize;
pthread_t *threads;
todo_t *qhead;
todo_t *qtail;
pthread_mutex_t qlock;
pthread_cond_t q_not_empty;
pthread_cond_t q_empty;
int shutdown;
int dont_accept;
}threadpool_t;
typedef struct TODO_T
{
void (*routine) (void*);
void * arg;
int lock;
struct todo_t* next;
} todo_t;
The function assigned to the pthread
/********************************************************************
*
* do_work:
*
* this is the reusable thread, assigned work via the dispatch
* function.
*
********************************************************************/
void* do_work(void *p)
{
int c = 0;
thread_args_t *thread_args = (thread_args_t*)p;
threadpool_t *pool = thread_args->threadpool;
todo_t* workload;
wl_ctrl_t volatile *wcc = thread_args->wl_ctrl;
while(1)
{
pool->qsize = pool->qsize;
/* while work que is empty, spinlock */
while( pool->qsize == 0)
{
if(c<1)
printf("thread: %d spin-lock \n", thread_args->thread_id);
c++;
}
/* update the threadpool, minus current workload */
workload = pool->qhead;
pool->qsize--;
if(pool->qsize == 0)
{
pool->qhead = NULL;
pool->qtail = NULL;
}
else
{
pool->qhead = workload->next;
}
/* execute workload */
(workload->routine) (workload->arg);
free(workload);
/* check this threads wait state */
printf("In thread: %d\n",wcc->thread_state_control[thread_args->thread_id].active);
}
}

Is there a safe method to check if a pthread exists?

I'm testing an idea for detailed error handling, and want to enable a thread to have the ability to call a 'getlasterror' function when it needs to work with the error. I'm using a cheap and simple pointer-to-pointers for the structs, but also make use of the pthread_t id to overwrite a previous entry (if the error info was not needed or has been processed).
From the stackoverflow posts How do you query a pthread to see if it is still running? and How do I determine if a pthread is alive?, it seems using pthread_kill to send a fake signal is potentially unsafe. Is there really no alternative mechanism to check if a pthread with an id exists or not? Or can I disable the ability for thread ids to be reused at runtime? (I'm aware the latter may be a security issue...)
I'd not previously written any code, but I whipped up roughly what my plan would look like below in leafpad (so ignore any syntax errors, if any!). Point of interest is naturally the dynamic cleanup, there's no problem if the application is closing. Any other alternative ideas would also be welcome :)
If applicable, this will be a client/server program, hence a new thread will exist with each accept().
struct error_info_structs
{
struct error_info** errs; // error_info struct with details
pthread_t** tids; // thread ids for each struct
uint32_t num; // number of error_info structs and thread ids
pthread_mutex_lock lock; // runtime locker
};
struct error_info_structs g_errs;
// assume we've done necessary initialization...
struct error_info*
get_last_runtime_error()
{
struct error_info* retval = NULL;
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
retval = g_errs.errs[i];
goto release_lock;
}
}
release_lock:
pthread_mutex_unlock(&g_errs.lock);
return retval;
}
void
raise_runtime_error(struct error_info* ei)
{
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
// replace existing
memcpy(&g_errs.errs[i], ei, sizeof(error_info));
goto release_lock;
}
/*
* Dynamic cleanup to lower risk of resource exhaustion.
* Do it here, where we actually allocate the memory, forcing
* this to be processed at least whenever a new thread raises
* an error.
*/
if ( pthread_kill(g_errs.tids[i], 0) != 0 )
{
// doesn't exist, free memory. safe to adjust counter.
free(g_errs.errs[i]);
free(g_errs.tids[i]);
g_errs.num--;
}
}
/*
* first error reported by this thread id. allocate memory to hold its
* details, eventually free when thread no longer exists.
*/
struct error_info* newei = malloc(sizeof(struct error_info));
if ( newei == NULL )
{
goto release_lock;
}
pthread_t* newt = malloc(sizeof(pthread_t));
if ( newt == NULL )
{
free(newei);
goto release_lock;
}
// realloc-bits omitted
g_errs.errs[g_errs.num] = newei;
g_errs.tids[g_errs.num] = newt;
g_errs.num++;
release_lock:
pthread_mutex_unlock(&g_errs.lock);
}
... can I disable the ability for thread ids to be reused at runtime?
No, you can't.

thread local storage of a function

I am working on a program that requires a queue operation to be performed in multi threaded environment.
I am not sure about the thread local storage for a function, not just a global variable
i tried
__thread int head,tail;
__thread int q[MAX_NODES+2];
__thread void enqueue (int x) {
q[tail] = x;
tail++;
color[x] = GRAY;
}
__thread int dequeue () {
int x = q[head];
head++;
color[x] = BLACK;
return x;
}
I got following error
fordp.c:71: error: function definition declared '__thread'
fordp.c:77: error: function definition declared '__thread'
I read somewhere that a function is already thread safe unless its using shared variables so I tried
__thread int head,tail;
__thread int q[MAX_NODES+2];
void enqueue (int x) {
q[tail] = x;
tail++;
color[x] = GRAY;
}
int dequeue () {
int x = q[head];
head++;
color[x] = BLACK;
return x;
}
It did compile with no error, but my execution result was wrong hinting queue didnt work well with multi-threaded platform.
Can someone please explain me what is going on here??
Any help is appreciated.
__thread advises the compiler to create an instance of the variable for every thread.
I doubt that's what you want for the queue, it's head and tail the threads should concurrently operate on, as modifications done by one thread would not be visible by any other thread.
So do not use __thread here, but protect the concurrent access to the global variables, for example using one or more mutexes.
For your reference: http://en.wikipedia.org/wiki/Thread-local_storage
I think you're tackling the problem in the wrong way.
Your problem is that you want to associate a Queue object with a function call (e.g. enqueue).
In C these objects are usually referred to as contexts.
What you did is a variation of a global variable. Using per thread local storage is good for scratch space or actual per thread resources. and this is not the case.
The only option to have thread safety and correctness is to add the context to the function call.
I removed the reference to color to simplify things.
struct queue {
unsigned head, tail;
int q[MAX_NODES+2];
};
void enqueue (struct queue* q, int x) {
q->q[q->tail++] = x;
}
int dequeue (struct queue* q) {
int x = q->q[q->head++];
return x;
}
Note: you should perform checks on pointers and indexes.

Resources