Reputation: 3529
I have probably pointer problem with fp, cause I get (SIGSEGV) error.
But I'm not much experienced in C and I doesn't see it.
What I'm trying to do. I do Server application for simple game, I handle clients in new threads. I use function pthread_create, it has handle function called handle_client, I need to get in some argumets socketdescritpor(it works) and filedescriptor for writing logs(there is probably the problem).
In my main I open the log file, then I put the filedescriptor to my struct, I get the struct inside the handle_client function and in this function I want to get back the file decriptor (fp
) of the log file, to be able write to file. I use fflush(fp) to save the data after each fprintf, I open the file once and then each client should be able write to file throuhgt this descripor, but I've probably done something bad with pointers (I mean geting fp
in and out from the struct, there is piece of my code where I do this action.) Thx for help.
struct
typedef struct
{
int fd;
FILE *fp; //filepointer for logs file
} my_thread_context_t;
main
int main(int argc, char *argv[]) {
FILE * fp;
fp = fopen("Serverlog.log","w");//delete last file
fclose(fp);
fp = fopen("Serverlog.log","a+");
my_thread_context_t ctx;
//bind server
//listen
while(1) {
//accept
ctx.fp = fp;// add file pointer to structure
int check = pthread_create(&thread, NULL,handle_client,&ctx);
//other code
}
hadle_client function
void * handle_client(void * void_context){
my_thread_context_t * context = (my_thread_context_t *) void_context;
FILE *fp; //pointer na soubor s logy
fp = context->fp;//get the filepointer for logs
//other code ..
}
Upvotes: 0
Views: 531
Reputation: 6531
It looks like many threads can access your my_thread_context_t::fp
and that is exactly the problem. The FILE*
type is really a (opaque) pointer to structure used by the C library. This structure contents may get corrupted (or non-consistent) when more than one thread modifies it. You must synchronize access to your my_thread_context_t::fp
. I would suggest creating a mutex (see pthread_mutex_init
, pthread_mutex_lock
, pthread_mutex_unlock
) inside your ctx
structure. Each thread should lock it before it starts writing to a file and unlock it when its finished writing - a separate (inline) function for this puprpose would be even better design, e.g:
typedef struct
{
int fd;
pthread_mutex_t mutex;
FILE *fp; //filepointer for logs file
} my_thread_context_t;
my_thread_context_t ctx;
fp = fopen("Serverlog.log","a+");
pthread_mutex_init(&ctx.mutex);
ctx.fp = fp;
inline void write_to_log(my_thread_context_t* pCtx,const char* pcszMessage)
{
pthread_mutex_lock(&(pCtx->mutex));
/* here write to the log file */
pthread_mutex_unlock(&(pCtx->mutex));
}
If you do it this way, it is not only safe, but you also do not have to invoke fflush
after every write (unless you want your log to be always in sync).
Don't forget to call pthread_mutex_destroy
after all threads are finished (e.g. after all neccesary ptrhead_join
s).
Upvotes: 2