/* This is a server using System V IPC with signal handler to clean up the existing message queue */ #include #include #include #include #include #include #include #include #include #include // All globals that every thread should be able to see struct msgbufl { int mtype; char mtext[200]; }; pthread_mutex_t Screen_Lock; int mymsg; void *Worker(void *arg); void cleanup(int sig_num); #define COMMAND 1 #define RESPONSE 2 #define COMMAND_LEN 200 struct Wrapper { int rcvsize; struct msgbufl *msgp; }; int main(int argc, char **argv) { int ret, myuid; struct Wrapper *mywrapper; struct msgbufl *msg_rcvd; pthread_t worker_id; // set the INT (Ctrl-C) signal handler to 'cleanup' signal(SIGINT, cleanup); myuid = getuid(); //Initialize the mutex that protects the output and PVM send/receive pthread_mutex_init(&Screen_Lock, NULL); pthread_mutex_lock(&Screen_Lock); printf("Welcome to the auction database manager !\n"); pthread_mutex_unlock(&Screen_Lock); mymsg = msgget(myuid, (IPC_CREAT|IPC_EXCL|0400|0200)); if( mymsg<0) { perror("msgget error!"); exit(1); } printf("mymsg id = %d\n", mymsg); while(1) { printf("waiting for new message..\n"); msg_rcvd = (struct msgbufl *)malloc(sizeof(struct msgbufl)); ret = msgrcv(mymsg, msg_rcvd, COMMAND_LEN, COMMAND, MSG_NOERROR); if( ret<0 ) { perror("msgrcv error!"); free(msg_rcvd); if(msgctl(mymsg, IPC_RMID, NULL)<0) perror("server: msgctl error!!"); exit(0); } mywrapper = (struct Wrapper *)malloc(sizeof(struct Wrapper)); mywrapper->rcvsize = ret; mywrapper->msgp = msg_rcvd; pthread_create(&worker_id, NULL, Worker, (void *)mywrapper); } exit(0); } void *Worker(void *arg) { struct Wrapper *mywrapper=(struct Wrapper*)arg; char response[50]; int msgsize = mywrapper->rcvsize; pthread_mutex_lock(&Screen_Lock); printf("server received \" %s \"from t%d.\n", mywrapper->msgp->mtext,msgsize); pthread_mutex_unlock(&Screen_Lock); strcpy(response, "Server Response OK"); free(mywrapper); return NULL; } void cleanup(int sig_num) { signal(SIGINT, cleanup); /* On some systems (such as Linux), when a signal handler is called, * the system automatically resets the signal handler for that signal * to the default handler. Thus, we re-assign the signal handler immediately * when entering the handler function. Otherwise, the next time this signal * is received, the process will exit (default behavior for INT signals). * Even on systems that do not behave in this way, it still won't hurt, * so adding this line always is a good idea. */ /* we clean up the message queue */ if(msgctl(mymsg, IPC_RMID, NULL)<0) perror("server: msgctl error!!"); printf("Clean up then exit!\n"); fflush(stdout); exit(0); }