cpukit/posix/src/clocknanosleep.c: fix cancellation points

According to the POSIX standard, sleep/nanosleep/clock_nanosleep
should be treated as cancellation points.

Updates #4675
This commit is contained in:
tangkun
2025-07-22 14:58:03 +08:00
committed by Kinsey Moore
parent a350345e29
commit c20dc9c7aa
2 changed files with 60 additions and 1 deletions

View File

@@ -67,6 +67,8 @@ int clock_nanosleep(
Thread_Control *executing;
int eno;
pthread_testcancel();
if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
return ENOTSUP;
}
@@ -149,5 +151,6 @@ int clock_nanosleep(
#endif
}
pthread_testcancel();
return eno;
}

View File

@@ -35,6 +35,50 @@
const char rtems_test_name[] = "PSXCANCEL 1";
#define TIMEOUT 5
static int cleanup_flag;
/*
* Cleanup function that the thread executes when it is canceled. So if
* cleanup_flag is 1, it means that the thread was canceled.
*/
static void a_cleanup_func()
{
cleanup_flag = 1;
}
static void *a_thread_func()
{
int err;
err = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (err != 0) {
fprintf(stderr, "pthread_setcancelstate: %s", strerror(err));
goto thread_exit_failure;
}
err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
if (err != 0) {
fprintf(stderr, "pthread_setcanceltype: %s", strerror(err));
goto thread_exit_failure;
}
/* Set up the cleanup handler */
pthread_cleanup_push(a_cleanup_func, NULL);
/* Wait for a timeout period for the cancel request to be sent. */
sleep(TIMEOUT);
/* Should not get here, but just in case pthread_testcancel() didn't
* work -- the cancel request timed out. */
pthread_cleanup_pop(0);
thread_exit_failure:
cleanup_flag = -1;
return NULL;
}
/* forward declarations to avoid warnings */
void *POSIX_Init(void *argument);
@@ -135,6 +179,7 @@ void *POSIX_Init(
rtems_status_code status;
int eno;
void *value;
pthread_t new_th;
TEST_BEGIN();
@@ -156,6 +201,17 @@ void *POSIX_Init(
rtems_test_assert( eno == 0 );
rtems_test_assert( value == PTHREAD_CANCELED );
status = pthread_create(&new_th, NULL, a_thread_func, NULL);
rtems_test_assert( !status);
/* Remove potential for race */
sleep(TIMEOUT / 2);
status = pthread_cancel(new_th);
rtems_test_assert( !status);
status = pthread_join(new_th, NULL);
rtems_test_assert( !status);
rtems_test_assert(cleanup_flag == 1);
TEST_END();
rtems_test_exit(0);
return NULL; /* just so the compiler thinks we returned something */
@@ -170,7 +226,7 @@ void *POSIX_Init(
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
#define CONFIGURE_MAXIMUM_POSIX_THREADS 4
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT