blob: c8665afb38db6ef6bfccb1934e2f8fa1f37a22e9 [file] [log] [blame]
/*
* Copyright (c) 2003, Intel Corporation. All rights reserved.
* Created by: julie.n.fleischer REMOVE-THIS AT intel DOT com
* This file is licensed under the GPL license. For the full content
* of this license, see the COPYING file at the top level of this
* source tree.
*/
/*
* Test mq_timedsend() will set errno == EINTR if it is interrupted by a signal.
*
* Steps:
* 1. Create a thread and set up a signal handler for SIGUSR1
* 2. Thread indicates to main that it is ready to start calling mq_timedsend until it
* blocks for a timeout of 10 seconds.
* 3. In main, send the thread the SIGUSR1 signal while mq_timedsend is blocking.
* 4. Check to make sure that mq_timedsend blocked, and that it returned EINTR when it was
* interrupted by SIGUSR1.
*
*/
#include <stdio.h>
#include <pthread.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include "posixtest.h"
#define NAMESIZE 50
#define MSGSTR "0123456789"
#define BUFFER 40
#define MAXMSG 10
#define INTHREAD 0
#define INMAIN 1
int sem; /* manual semaphore */
int in_handler; /* flag to indicate signal handler was called */
int errno_eintr; /* flag to indicate that errno was set to eintr when mq_timedsend()
was interruped. */
/*
* This handler is just used to catch the signal and stop sleep (so the
* parent knows the child is still busy sending signals).
*/
void justreturn_handler(int signo)
{
/* Indicate that the signal handler was called */
in_handler=1;
return;
}
void *a_thread_func()
{
int i;
struct sigaction act;
char gqname[NAMESIZE];
mqd_t gqueue;
const char *msgptr = MSGSTR;
struct mq_attr attr;
struct timespec ts;
/* Set up handler for SIGUSR1 */
act.sa_handler=justreturn_handler;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
sigaction(SIGUSR1, &act, 0);
/* Set up mq */
sprintf(gqname, "/mq_timedsend_12-1_%d", getpid());
attr.mq_maxmsg = MAXMSG;
attr.mq_msgsize = BUFFER;
gqueue = mq_open(gqname, O_CREAT |O_RDWR, S_IRUSR | S_IWUSR, &attr);
if (gqueue == (mqd_t)-1) {
perror("mq_open() did not return success");
pthread_exit((void*)PTS_UNRESOLVED);
return NULL;
}
/* mq_timedsend will block for 10 seconds when it waits */
ts.tv_sec=time(NULL)+10;
ts.tv_nsec=0;
/* Tell main it can go ahead and start sending SIGUSR1 signal */
sem = INMAIN;
for (i=0; i<MAXMSG+1; i++) {
if (mq_timedsend(gqueue, msgptr,
strlen(msgptr), 1, &ts) == -1) {
if (errno == EINTR) {
if (mq_unlink(gqname) != 0) {
perror("mq_unlink() did not return success");
pthread_exit((void*)PTS_UNRESOLVED);
return NULL;
}
printf("thread: mq_timedsend interrupted by signal and correctly set errno to EINTR\n");
errno_eintr=1;
pthread_exit((void*)PTS_PASS);
return NULL;
} else {
printf("mq_timedsend not interrupted by signal or set errno to incorrect code: %d\n", errno);
pthread_exit((void*)PTS_FAIL);
return NULL;
}
}
}
/* Tell main that it the thread did not block like it should have */
sem = INTHREAD;
perror("Error: thread never blocked\n");
pthread_exit((void*)PTS_FAIL);
return NULL;
}
int main()
{
pthread_t new_th;
int i;
/* Initialized values */
i = 0;
in_handler=0;
errno_eintr=0;
sem = INTHREAD;
if (pthread_create(&new_th, NULL, a_thread_func, NULL) != 0)
{
perror("Error: in pthread_create\n");
return PTS_UNRESOLVED;
}
/* Wait for thread to set up handler for SIGUSR1 */
while (sem==INTHREAD)
sleep(1);
while ((i != 10) && (sem==INMAIN))
{
/* signal thread while it's in mq_timedsend */
if (pthread_kill(new_th, SIGUSR1) != 0)
{
perror("Error: in pthread_kill\n");
return PTS_UNRESOLVED;
}
i++;
}
if (pthread_join(new_th, NULL) != 0)
{
perror("Error: in pthread_join()\n");
return PTS_UNRESOLVED;
}
/* Test to see if the thread blocked correctly in mq_timedsend, and if it returned
* EINTR when it caught the signal */
if (errno_eintr != 1)
{
if (sem==INTHREAD)
{
printf("Test FAILED: mq_timedsend() never blocked for any timeout period.\n");
return PTS_FAIL;
}
if (in_handler != 0)
{
perror("Error: signal SIGUSR1 was never received, and/or the signal handler was never called.\n");
return PTS_UNRESOLVED;
}
}
printf("Test PASSED\n");
return PTS_PASS;
}