I am writing a multi-process program using named semaphores, in the master process I am opening the semaphore with the following code
semaphore = sem_open("/msema",O_RDWR|O_CREAT|O_TRUNC,00777,1);
if (semaphore == SEM_FAILED)
perror("SEMAPHORE");
and in the child program
count_sem=sem_open("/msema",O_RDWR);
if(count_sem==SEM_FAILED)
{
perror("sem_open");
return 1;
}
on sem_wait()
do {
errno=0;
printf("BeforeSemWait\n");
rtn=sem_wait(count_sem);
printf("afterSemWait\n");
} while(errno==EINTR);
if(rtn < 0) {
printf("Error\n");
perror("sem_wait()");
sem_close(count_sem);
return 1;
}
I am getting a bus error from sem_wait()
BeforeSemWait
Program received signal SIGBUS, Bus error.
0x00a206c9 in sem_wait##GLIBC_2.1 () from /lib/libpthread.so.0`
What am I doing wrong?
edit: entire code:
master.c: http://pastebin.com/3MnMjUUM
worker.c http://pastebin.com/rW5qYFqg
You must have somewhere else a bug in your program. The following works here (O_TRUNC is not needed):
semproducer.c:
#include <fcntl.h>
#include <stdio.h>
#include <semaphore.h>
int main () {
sem_t *sem=sem_open("/msema",O_RDWR|O_CREAT /* |O_TRUNC*/ ,00777,1);
if (sem==SEM_FAILED) {
perror("sem_open");
}
else {
while (1) {
sem_post (sem);
printf ("sem_post done\n");
sleep (5);
}
}
}
semconsumer.c:
#include <fcntl.h>
#include <stdio.h>
#include <semaphore.h>
#include <errno.h>
int main () {
sem_t *count_sem=sem_open("/msema",O_RDWR);
if(count_sem==SEM_FAILED) {
perror("sem_open");
return 1;
}
do {
int rtn;
do {
errno=0;
rtn=sem_wait(count_sem);
} while(errno==EINTR);
if(rtn < 0) {
perror("sem_wait()");
sem_close(count_sem);
return 1;
}
printf ("sema signalled\n");
} while (1);
}
compile with gcc semproducer.c -o semproducer -lrt and gcc semconsumer.c -o semconsumer -lrt
I encountered this exact error.
It was because I hadn't linked in the Real-Time library that provides POSIX real-time functionality. The commenter above briefly mentioned the "-lrt" parameter in his solution, but did not emphasize it as the reason that you were getting your exception. You can verify this with the following code:
int main(void)
{
sem_t* my_sem = sem_open("/test_sem", O_CREAT, S_IRUSR | S_IWUSR, 0);
sem_wait(my_sem);
}
Assuming this is in the file "test.c" and I run the following:
gcc ./test.c -o test.out
./test.out
I get the Bus Error Output:
Bus error
But with the following command:
gcc ./test.c -o test.out -lrt
./test.out
The program does not except, and instead waits on the semaphore forever which is expected with a value of zero.
You should NOT pass -lrt, however. The linux documentation for sem_wait(3) indicates that the correct command is "-pthread". Substituting "-lrt" with "-pthread" in my testing indicates that it has the same effect, so the list of flags passed by -pthread on Linux likely includes "-lrt".
As such, the correct compiler invocation would be
gcc ./test.c -o test.out -pthread
Related
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.
I want to specify during run-time to ignore a function call for a function (which is of course defined) inside my executable. Please suggest some methodology for doing the same in C language on Linux.
Probably the best you can do is something like this:
// Filename mycode.c
int main()
{
// ...
#ifndef SOME_MACRO
someFUnction();
#endif
//...
}
int someFUnction()
{
// does something
}
To exclude the function call in main, you need to compile with
gcc -DSOME_MACRO mycode.c
If you will compile simply as
gcc mycode.c
then the function call will be enabled.
You cannot ignore function calls at runtime, you either call the function or you don't.
But let's assume for the sake of this answer that there exists a condition under which the function gets called and at least another condition under which the function is not called.
You can tell the program these conditions in several ways, for example per command-line, change of environment/file, and probably a long list more. For simplicity let's use the command-line and give the conditions in form of a argument to the executable. Additionally, because it is simple and short, use a signal.
File optional_functions.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
static void a(void)
{
puts("Function \"a\" called");
}
static void b(void)
{
puts("Function \"b\" called");
}
static void c(void)
{
puts("Function \"c\" called (by signal SIGINT)");
}
#include<signal.h>
#include<unistd.h>
static void signal_handler(int signal_number)
{
if (signal_number == SIGINT) {
c();
exit(EXIT_SUCCESS);
}
}
int main(int argc, char **argv)
{
void *dynlib;
void (*function_d) (void);
char *dynlib_error;
if (argc == 2) {
if (argv[1][0] == 'a') {
a();
} else if (argv[1][0] == 'b') {
b();
} else if (argv[1][0] == 'd') {
puts("External function \"d\" wanted, loading library");
dynlib = dlopen("libfunctiond.so", RTLD_LAZY);
if (dynlib == NULL) {
fprintf(stderr, "Failed loading lib: %s\n", dlerror());
exit(EXIT_FAILURE);
}
*(void **) (&function_d) = dlsym(dynlib, "d");
dynlib_error = dlerror();
if (dynlib_error != NULL) {
fprintf(stderr, "Failed calling function \"d\" fom lib: %s\n",
dynlib_error);
exit(EXIT_FAILURE);
}
(*function_d) ();
} else {
fprintf(stderr, "A function named \"%c\" does not exist, bailing out\n",
argv[1][0]);
exit(EXIT_FAILURE);
}
} else {
if (signal(SIGINT, signal_handler) == SIG_ERR) {
fprintf(stderr, "signal catching failed, bailing out\n");
exit(EXIT_FAILURE);
}
sleep(5);
puts("Signal catching timed out, assuming no function wanted in the first place.");
}
exit(EXIT_SUCCESS);
}
File functiond.h
#ifndef FUNCTIOND_H
#define FUNCTIOND_H
void d(void);
#endif
File functiond.c
#include <stdio.h>
#include "functiond.h"
void d(void)
{
puts("Function \"d\" called and says hello from the library");
}
Compile as
clang -Weverything -fPIC -c functiond.c
clang -shared -Wl,-soname,libfunctiond.so.1 -o libfunctiond.so.1.0 functiond.o
ln -sf libfunctiond.so.1.0 libfunctiond.so.1
ln -sf libfunctiond.so.1 libfunctiond.so
clang -Weverything -o optional_functions optional_functions.c example.c -ldl
Run it
$ ./optional_functions # waiting 5 seconds
Signal catching timed out, assuming no function wanted in the first place.
$ ./optional_functions # press CTRL+c in less than 5 seonds
^CFunction "c" called (by signal SIGINT)
$ ./optional_functions 1
A function named "1" does not exist, bailing out.
$ ./optional_functions a
Function "a" called
$ ./optional_functions b
Function "b" called
$ ./optional_functions d
External function "d" wanted, loading library
Failed loading lib: libfunctiond.so: cannot open shared object file: No such file or directory
That was expected. Either give dlopen() the complete path to the library or let the environment variable LD_LIBRARY_PATH do the job:
$ LD_LIBRARY_PATH=. ./optional_functions d
External function "d" wanted, loading library
Function "d" called and says hello from the library
It is not the proper way to make, install and and use dynamic libraries, of course, but again: for the sake of simplicity…
I am currently writing a shared library that takes a UNIX username and returns a string with all of the groups that user belongs to in [group1, group2, group3...] format.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <utmp.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
int num_groups = 0;
struct passwd *pwd;
gid_t *groups;
struct group *grp;
FILE *stream;
char *buff;
size_t length;
char *printGroups(char *arg)
{
stream = open_memstream(&buff, &length);
pwd = getpwnam(arg);
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
groups = malloc(num_groups * sizeof(gid_t));
if (groups == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
fprintf(stream, " [");
for (int i = 0; i < num_groups; ++i){
grp = getgrgid(groups[i]);
if (i == num_groups - 1)
fprintf(stream, "%s", grp->gr_name);
else
fprintf(stream, "%s ", grp->gr_name);
}
free(groups);
fprintf(stream, "]");
fclose(stream);
return buff;
}
This is main function in my shared library that returns the string. I verified that the function is indeed correct - the same logic works in a standalone program using printf instead of open_memstream stringstream.
The library however segfaults and I can't pinpoint why. Valgrind does not output anything useful:
gcc -shared -fpic -g -Wall lib.c
valgrind ./a.out
==9916== Process terminating with default action of signal 11 (SIGSEGV)
==9916== Access not within mapped region at address 0x0
==9916== at 0x1: ???
==9916== by 0xFFF000672: ???
Same goes for gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? () (gdb) backtrace
#0 0x0000000000000001 in ?? ()
#1 0x00007fffffffe6e9 in ?? ()
#2 0x0000000000000000 in ?? ()
I am out of ideas. Could somebody point me to a solution, ethier an error in the .so source or the reason why both Valgrind and gdb print ??? despite using the -g flag when compiling?
It looks like you're attempting to run the shared library directly. That's not how shared libraries work. They're referenced by other programs that use them.
For example, this code would use your library:
#include <stdio.h>
#include <stdlib.h>
char *printGroups(char *);
int main()
{
char *groups = printGroups("root");
printf("groups: %s\n", groups);
free(groups);
return 0;
}
If you first compile your library like this:
gcc -shared -fpic -g -Wall lib.c -o libmylib.so
Then, assuming this library lives in the same directory as the the above test code, you compile the test code like this:
gcc -g -Wall -Wextra -L. -o mytest mytest.c -lmylib
Then set an environment variable to find your library:
export LD_LIBRARY_PATH=.
You can then run the test program which will use your library.
I'm trying to install zeromq but I'm having some problems with undefined reference . I used this tutorial to install zeromq in my machine, with the difference that I downloaded version 4.1.4 and not 4.1.2.
Then I'm trying to run the following code (got from zeromq tutorial) in C:
// Hello World server
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
// Socket to talk to clients
void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 10, 0);
printf ("Received Hello\n");
sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}
with this line:
gcc program.c -lzmq
and I got this error:
/tmp/cc3OkNsE.o: In function `main':
program.c:(.text+0x18): undefined reference to `zmq_ctx_new'
collect2: error: ld returned 1 exit status
I already did some research but I couldn't find any clear solutions/instructions. Anyone knows how to solve it or what I'm doing wrong?
As pointed by Maarten Artis in the comments above, it wasn't actually linking the library. The correct command line is:
gcc -Wall program.c -o prog -L/usr/local/lib -lzmq
I can compile this program which was provided to me, but that I must further develop. I have some questions about it:
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define TIMEOUT (20)
int main(int argc, char *argv[])
{
pid_t pid;
if(argc > 1 && strncmp(argv[1], "-help", strlen(argv[1])) == 0)
{
fprintf(stderr, "Usage: RunSafe Prog [CommandLineArgs]\n\nRunSafe takes as arguments:\nthe program to be run (Prog) and its command line arguments (CommandLineArgs) (if any)\n\nRunSafe will execute Prog with its command line arguments and\nterminate it and any remaining childprocesses after %d seconds\n", TIMEOUT);
exit(0);
}
if((pid = fork()) == 0) /* Fork off child */
{
execvp(argv[1], argv+1);
fprintf(stderr,"RunSafe failed to execute: %s\n",argv[1]);
perror("Reason");
kill(getppid(),SIGKILL); /* kill waiting parent */
exit(errno); /* execvp failed, no child - exit immediately */
}
else if(pid != -1)
{
sleep(TIMEOUT);
if(kill(0,0) == 0) /* are there processes left? */
{
fprintf(stderr,"\nRunSafe: Attempting to kill remaining (child) processes\n");
kill(0, SIGKILL); /* send SIGKILL to all child processes */
}
}
else
{
fprintf(stderr,"RunSafe failed to fork off child process\n");
perror("Reason");
}
}
What does my warning mean when I compile it?
$ gcc -o RunSafe RunSafe.c -lm
RunSafe.c: In function ‘main’:
RunSafe.c:30:44: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
Why can't I execute the file?
$ file RunSafe
RunSafe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x0a128c8d71e16bfde4dbc316bdc329e4860a195f, not stripped
ubuntu#ubuntu:/media/Lexar$ sudo chmod 777 RunSafe
ubuntu#ubuntu:/media/Lexar$ ./RunSafe
bash: ./RunSafe: Permission denied
ubuntu#ubuntu:/media/Lexar$ sudo ./RunSafe
sudo: ./RunSafe: command not found
First, you need to #include <string.h> to get rid of that warning.
Second, the OS is probably preventing you from executing programs on the /media/Lexar filesystem, no matter what their permission bits are. If you type mount you'll probably see the noexec option for /media/Lexar.
warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
You need to include #include<string.h> because strlen() is declared in it.
Try running the exe on some other location in your filesystem and not the mounted partition as the error indicates for some reason you don't have permissions on that mounted partition.