For some reason, pthread_join always causes a SIGSEGV action on my computer when I run with Valgrind. To test this, I ran the following code from https://computing.llnl.gov/tutorials/pthreads/:
/* pthread.c */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status of %ld\n",
t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
Running
$ clang -g -o pthread pthread.c
$ valgrind --leak-check=full ./pthread
Yields the following valgrind error:
==17283== Process terminating with default action of signal 11 (SIGSEGV)
==17283== Access not within mapped region at address 0x700002F3CC3E
==17283== at 0x10044437F: _pthread_find_thread (in /usr/lib/system/libsystem_pthread.dylib)
==17283== by 0x100446D52: _pthread_join_cleanup (in /usr/lib/system/libsystem_pthread.dylib)
==17283== by 0x100446C63: pthread_join (in /usr/lib/system/libsystem_pthread.dylib)
==17283== by 0x100000D52: main (pthread.c:50)
My Computer is a Mac OS X (El Capitan). For clang, I am using Apple LLVM version 7.0.2 (clang-700.1.81). For Valgrind I am using valgrind-3.11.0.
I was unable to reproduce your problem on my Mac OS X Yosemite (10.10.5) with kernel 14.5.0. The Clang and Valgrind versions I use are the same as yours (please double check just in case):
$ clang --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
$ valgrind --version
valgrind-3.11.0
Thus the only difference is the OS version. Here are the steps I followed:
Refreshed the installation of the developer tools by running
xcode-select --install. Without doing this I could not build
Valgrind.
Set the CC and CXX environment variables to clangand
clang++, respectively. I did this to ensure that Clang, not GCC,
is used. Setting CXX was probably overkill. I later wiped out the Valgrind installation and re-did it
with GCC, but it was still a success, even though I think I was
getting more warnings.
Did ./configure --prefix=/usr/local in the root of the untarred
Valgrind tarball, followed by make and sudo make install.
Hopefully these steps help you resolve the issue.
Related
Looking at the output of readelf -s /lib/x86_64-linux-gnu/libc.so.6 on my Ubuntu 22.04 box, I see (what looks to be) the entire pthread API contained in the .text section.
As a sanity check, I successfully compiled and ran
#include <stdio.h>
#include <string.h>
#include <pthread.h>
static void *
func(void *args) {
return args;
}
int main() {
int ret;
pthread_t thread;
ret = pthread_create(&thread, NULL, func, NULL);
if ( ret != 0 ) {
fprintf(stderr, "pthread_create: %s\n", strerror(ret));
return ret;
}
pthread_join(thread, NULL);
return 0;
}
without using -pthread.
Given all of this, is there any purpose to libpthread on my computer other than providing support for older applications which expect it to be there?
Is libpthread needed if the pthread API is in libc
No.
is there any purpose to libpthread on my computer other than providing support for older applications which expect it to be there?
No.
See https://developers.redhat.com/articles/2021/12/17/why-glibc-234-removed-libpthread . Since then libpthread is an empty library.
I was having a problem with one application, so i went back to the basics and grabbed the sem_timedwait example from the ubuntu focal online manpages. I modified it slightly to repro the problem.
CASE: sem_post before sem_timedwait
EXPECTED: sem_timedwait to succeed immediately
OBTAINED: sem_timedwait times out
The problem was showing initially on a Docker (WSL disabled) container with Ubuntu 20.04 (g++ 9 multilib)
I then tried from a WSL Debian 9 (g++ 6 multilib) and a WSL Ubuntu 20.04 (g++ 9 multilib) installed fresh from PowerShell
I further installed a full fresh Ubuntu 20.04 VM with g++ 9 multilib on Hyper-V
I also tried apt update && apt upgrade to be sure to be on the latest packages, I also tried at some point to completely remove g++ 9 and all its dependencies and use g++ 10 (which comes with libasan.so.6 instead of libasan.so.5)
Original sem_timedwait example from Ubuntu
Modified version, added a sleep before sem_timedwait so that the call to sem_timedwait happens always after the sem_post. I also added a print of sem_getvalue to verify that the semaphore counter was being incremented correctly to 1.
[File: test_sem.cpp]
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
sem_t sem;
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void
handler(int sig)
{
write(STDOUT_FILENO, "sem_post() from handler\n", 24);
if (sem_post(&sem) == -1) {
write(STDERR_FILENO, "sem_post() failed\n", 18);
_exit(EXIT_FAILURE);
}
}
int
main(int argc, char *argv[])
{
struct sigaction sa;
struct timespec ts;
int s;
if (argc != 3) {
fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sem_init(&sem, 0, 0) == -1)
handle_error("sem_init");
/* Establish SIGALRM handler; set alarm timer using argv[1] */
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGALRM, &sa, NULL) == -1)
handle_error("sigaction");
alarm(atoi(argv[1]));
/* Calculate relative interval as current time plus
number of seconds given argv[2] */
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
handle_error("clock_gettime");
ts.tv_sec += atoi(argv[2]);
//this is a cancellation point when the alarm goes off
sleep(atoi(argv[1]) + 2);
int value = 0;
sem_getvalue(&sem, &value);
printf("sem_getvalue(): %d\n", value);
sleep(2);
printf("main() about to call sem_timedwait()\n");
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue; /* Restart if interrupted by handler */
/* Check what happened */
if (s == -1) {
if (errno == ETIMEDOUT)
printf("sem_timedwait() timed out\n");
else
perror("sem_timedwait");
} else
printf("sem_timedwait() succeeded\n");
exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
}
to compile this example i used the following
g++ -std=gnu++17 -m32 -fsanitize=address -fsanitize-recover=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer test_sem.cpp -lstdc++ -lpthread -lasan
to run it, simply ./a.out 2 5
what I obtain is the following unexpected result:
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() timed out
the same code compiled WITHOUT the -m32 flag g++ -std=gnu++17 -fsanitize=address -fsanitize-recover=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer test_sem.cpp -lstdc++ -lpthread -lasan gives me the following expected result
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() succeeded
the same code compiled WITH the -m32 flag but WITHOUT the libasan g++ -std=gnu++17 -m32 test_sem.cpp -lstdc++ -lpthread -lasan gives me the following expected result:
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() succeeded
Just for the sake of me I tried also to replace the signal handler code with a second thread to achieve the same sem_post before sem_timedwait and I obtain the same exact result. I further tried also using the non-POSIX-compliant sem_clockwait using both CLOCK_REALTIME and CLOCK_MONOTONIC and I got the same exact result.
I also tried completely removing g++ 9 and installed g++ 10 (which uses libasan.so.6 instead of libasan.so.5)
Right now I dont know if it is something on my side but seems that Docker Ubuntu 20.04 (no WSL), Debian 9 WSL 2, Ubuntu 20.04 WLS 2, and full Hyper-V Virtual Machine with Ubuntu 20.04 are all giving me the same result.
I tried everything I could think of to no avail.
#include <stdio.h>
#include <sys/wait.h>
#include <pthread.h>
void* runfunc(void* arguments){
printf("in run thread\n");
return NULL;
}
int main(void)
{
pthread_t pthread_id;
pthread_create(&pthread_id, NULL, runfunc, NULL);
printf("after pthread creation\n");
return 0;
}
$ gcc -pthread intro.c
$ ./a.out
after pthread creation
in run thread
in run thread
$ ./a.out
after pthread creation
$
There are 4 types of outputs for this program on linux.
"after pthread creation" -> this output can be easily understood as before thread execution process completes and exits and deletes all threads.
"after pthread creation
in " -> this output can also be understood as while process was exiting thread executed a little bit to print in
"in running thread
after pthread creation" -> this output can also be easily understood
"after pthread creation
in running thread
in running thread" -> now i don't get why am i getting "in running thread" 2 times instead of once.
Linux implementation of threads is considered.
I get a unknown error code (it's actually 48) when trying to set the scheduling policy to SCHED_RR for my thread.
Here is a sample of my code:
#include <sched.h>
#include <pthread.h>
#include <stdio.h>
int main() {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
int ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
printf("ret: %s\n", strerror(ret));
return 0;
}
Trace:
ret: Unknown error
Why is that so? It's not EPERM like I've seen in other questions.
I'm on Windows 7 using cygwin.
If you read the documentation of pthreads in cygwin:
https://sourceware.org/pthreads-win32/announcement.html
you can see that only SCHED_OTHER is supported:
pthread_attr_setschedpolicy (only supports SCHED_OTHER)
I am testing a small code which involves creating a thread on my ARMv8 device.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *fun(void *arg)
{
sleep(2);
printf("%s: Exiting now\n", __func__);
pthread_exit(0);
//return 0;
}
int main()
{
pthread_t th;
pthread_create(&th, NULL, fun, NULL);
sleep(3);
printf("%s: Wait over\n", __func__);
return 0;
}
When I compile the code into a 32-bit executable and run it on the device, it seems to run fine.
fun: Exiting now
main: Wait over
But when I build it into 64-bit executable, I get the following output:
fun: Exiting now
Aborted (core dumped)
As far as I know, ARMv8 is completely backward-compatible. But here, the 32-bit binary runs while 64-bit binary hangs up.
Apart from that, while trying out things, I found when I change the fun() to:
void *fun(void *arg)
{
sleep(2);
printf("%s: Exiting now\n", __func__);
//pthread_exit(0);
return 0;
}
Both 32-bit and 64-bit binaries run fine.
I looked into this article:
Pthread: Why people bother using pthread_exit? and didn't get much information as to where the problem might be.
Here is some more information about my device:
Linux Version: Linux version 4.4.67 (lnxbuild#ecbld-bd213-lnx) (gcc version 4.9.3 (GCC) ) #1 SMP PREEMPT
Total Memory : 3721056
So here are my questions:
Can there be any reason why the 32-bit binary runs while the 64-bit crashes on an ARMv8 device?
How does this error fix when I replace pthread_exit(0) with return 0?
Is there anything else that I might be missing here?
Minor Update:
I have tried changing the wait times and making various combinations of pthread_join(), pthread_detach() and pthread_exit() at all possible places, but to no avail. This is the simplest version I could provide.