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)
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'm trying to debug a linux user-space application, which creates a process group with setpgid(0,0). When launched on terminal, it returns no error and work as expected. But when debugging with gdb, it returns EPERM.
I suspect that it is because the gdb attaches my process as a child. So it is not possible to set my process as parent with setpgid(0,0). Is that correct? If so, isn't there a way to debug this case with gdb?
Edit:
Environment:
Ubuntu 12.04 Kernel 3.11.0-15-generic
Using the simple code below, if launched on terminal, I get success!!. If I debug with gdb (configured on Eclipse Luna), I get setpgid: Operation not permitted.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int err = setpgid((pid_t)0, (pid_t) 0);
if (err < 0)
perror("setpgid");
else
printf("success!! \n");
exit(err);
}
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.
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.
I am trying to interpose calls to pthread_cond_broadcast using LD_PRELOAD mechanism. My interposed pthread_cond_broadcast function just calls the original pthread_cond_broadcast. However, for a very simple pthread code where both pthread_cond_wait and pthread_cond_broadcast get invoked, I either end up with a segfault in glibc (for glibc 2.11.1) or the program hangs (for glibc 2.15). Any clues on that is going on?
The interposition code (that gets compiled as a shared library):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <dlfcn.h>
static int (*orig_pthread_cond_broadcast)(pthread_cond_t *cond) = NULL;
__attribute__((constructor))
static void start() {
orig_pthread_cond_broadcast =
(int (*)()) dlsym(RTLD_NEXT, "pthread_cond_broadcast");
if (orig_pthread_cond_broadcast == NULL) {
printf("pthread_cond_broadcast not found!!!\n");
exit(1);
}
}
__attribute__((__visibility__("default")))
int pthread_cond_broadcast(pthread_cond_t *cond) {
return orig_pthread_cond_broadcast(cond);
}
The simple pthread program:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t cond_mutex;
pthread_cond_t cond_var;
int condition;
void *thread0_work(void *arg) {
pthread_mutex_lock(&cond_mutex);
printf("Signal\n");
condition = 1;
pthread_cond_broadcast(&cond_var);
pthread_mutex_unlock(&cond_mutex);
return NULL;
}
void *thread1_work(void *arg) {
pthread_mutex_lock(&cond_mutex);
while (condition == 0) {
printf("Wait\n");
pthread_cond_wait(&cond_var, &cond_mutex);
printf("Done waiting\n");
}
pthread_mutex_unlock(&cond_mutex);
return NULL;
}
int main() {
pthread_t thread1;
pthread_mutex_init(&cond_mutex, NULL);
pthread_cond_init(&cond_var, NULL);
pthread_create(&thread1, NULL, thread1_work, NULL);
// Slowdown this thread, so the thread 1 does pthread_cond_wait.
usleep(1000);
thread0_work(NULL);
pthread_join(thread1, NULL);
return 0;
}
EDIT:
For glibc 2.11.1, gdb bt gives:
(gdb) set environment LD_PRELOAD=./libintercept.so
(gdb) run
Starting program: /home/seguljac/intercept/main
[Thread debugging using libthread_db enabled]
[New Thread 0x7ffff7436700 (LWP 19165)]
Wait
Signal
Before pthread_cond_broadcast
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff79ca0e7 in pthread_cond_broadcast##GLIBC_2.3.2 () from /lib/libpthread.so.0
(gdb) bt
#0 0x00007ffff79ca0e7 in pthread_cond_broadcast##GLIBC_2.3.2 () from /lib/libpthread.so.0
#1 0x00007ffff7bdb769 in pthread_cond_broadcast () from ./libintercept.so
#2 0x00000000004008e8 in thread0_work ()
#3 0x00000000004009a4 in main ()
EDIT 2:
(Solved)
As suggested by R.. (thanks!), the issue is that on my platform pthread_cond_broadcast is a versioned symbol, and dlsym gives the wrong version. This blog explains this situation in great detail: http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/
The call through your function seems to end up in a different version of the function:
With LD_PRELOAD: __pthread_cond_broadcast_2_0 (cond=0x804a060) at old_pthread_cond_broadcast.c:37
Without LD_PRELOAD: pthread_cond_broadcast##GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_broadcast.S:39
So your situation is similar to this question, i.e. you are getting incompatible versions of pthread functions: symbol versioning and dlsym
This page gives one way to solve the problem, though a bit complex: http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/