I've been trying to debug this for a few hours now and I'm still stuck...
I get a segmentation fault with a "mkfifo" call in this code (it is only a part of my entire code, since I figured the rest was not relevant here) :
#include "marketfunc.h"
#include "error.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define PIPE_PATH "./pipe.fifo"
struct myStruct
{
int x;
int y;
int z;
};
struct myStruct *s;
int main(int argc, char **argv)
{
s = malloc(sizeof(struct myStruct));
// 'int marketfunc_init(int x)' is defined in a perfectly working extern library
if(marketfunc_init(1) == -1) error("failed to initialize marketfunc library", 5);
printf("test1\n");
// Segmentation fault
if(mkfifo(PIPE_PATH, 0666) == -1) error("failed to create pipe", 1);
printf("test2\n");
//...
}
Which produces this output (executableFile beeing the name of my file):
test1
bin/executableFile: Segmentation fault (core dumped)
The gdb backtrace produces this:
#0 strchrnul () at ../sysdeps/x86_64/strchr.S:32
#1 0x00007ffff7a5ed82 in __find_specmb (format=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>)
at printf-parse.h:108
#2 _IO_vfprintf_internal (s=0x7fffffffb5a0, format=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>,
ap=0x7fffffffdd58) at vfprintf.c:1332
#3 0x00007ffff7a63f31 in buffered_vfprintf (s=s#entry=0x7ffff7dd41c0 <_IO_2_1_stderr_>,
format=format#entry=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>, args=args#entry=0x7fffffffdd58)
at vfprintf.c:2356
#4 0x00007ffff7a5eeae in _IO_vfprintf_internal (s=0x7ffff7dd41c0 <_IO_2_1_stderr_>,
format=format#entry=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>, ap=ap#entry=0x7fffffffdd58)
at vfprintf.c:1313
#5 0x00007ffff7b0c595 in error_tail (status=status#entry=4199947, errnum=errnum#entry=1,
message=message#entry=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>, args=args#entry=0x7fffffffdd58)
at error.c:201
#6 0x00007ffff7b0c6ed in __error (status=4199947, errnum=1,
message=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>) at error.c:251
#7 0x0000000000400b78 in main (argc=1, argv=0x7fffffffdf38) at src/executableFile.c:75
Though the "pipe.fifo" file is created...
Thanks in advance for your help !
EDIT:
error is simply defined as such in error.c and it's signature in error.h:
#include "error.h"
#include <stdlib.h>
#include <stdio.h>
void error(char *msg, int ret)
{
perror(msg);
exit(ret);
}
If you look at the stack trace, you will see that the call to error() shows up as:
0x00007ffff7b0c6ed in __error (status=4199947, errnum=1, message=0xffffffffffffff60 <error: Cannot access memory at address 0xffffffffffffff60>) at error.c:251
This is NOT the error() function that you defined. But rather, it is the error() function defined in error.h with the following signature:
void error(int status, int errnum, const char *format, ...);
See error.h.
As you can see, this function expects a char* format as the last argument, which is getting some junk off the stack 0xffffffffffffff60, because you don't pass in the third argument at all. It would seem that the linker is resolving the call to error() to the wrong function.
As a quick fix, I would rename things as follows:
rename your file `error.h` to `error_my.h`
your definition of `error()` to, say, `error_my()`
replace the calls to `error()` with `error_my()`.
Your code would look like:
#include "marketfunc.h"
#include "error_my.h" // <=======================
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define PIPE_PATH "./pipe.fifo"
struct myStruct
{
int x;
int y;
int z;
};
struct myStruct *s;
int main(int argc, char **argv)
{
s = malloc(sizeof(struct myStruct));
// 'int marketfunc_init(int x)' is defined in a perfectly working extern library
if(marketfunc_init(1) == -1) error_my("failed to initialize marketfunc library", 5); // <=======================
printf("test1\n");
// Segmentation fault
if(mkfifo(PIPE_PATH, 0666) == -1) error_my("failed to create pipe", 1); // <=======================
printf("test2\n");
//...
}
Print out errno when mkfifo() fails to figure out why it is failing in the first place.
Related
I have been trying to figure out how to do this for a day or two now. I have tried to copy code online too and I keep getting a segmentation fault for some reason and I don't have clue why.
Here is my code I currently have. (Copied from a YouTube video in which the code ran flawlessly.)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
int main(int argc, char *argv[]){
struct hostent *host_info;
struct in_addr *address;
char input[20];
strcpy(input, "stackoverflow.com");
printf("Will do a DNS query on: %s\n", input);
host_info = gethostbyname(input);
address = (struct in_addr *) (host_info->h_addr);
printf("%s has address %s\n", input, inet_ntoa(*address));
}
I guess most of the gethostbyname function fails to execute. You can check whether its return value is null. In addition, you can try the inet_ntop function instead of the inet_ntoa function.
I'm trying to write a multithreaded RPC server that returns a struct. Here's my XDR file. I'm running rpcgen -MN foo.x to generate multithreaded compatible code.
// foo.x
struct foo_out {
string name<128>;
};
program FOO_PROG {
version FOO_VERS {
foo_out foo(void) = 2;
} = 2 ;
} = 0x31230000;
Here's my server, you can see it takes a pointer to my struct, allocates some memory for the name string and then copies over the string. I also added a debug output
// foo_server.c
#include "foo.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
bool_t foo_2_svc(foo_out *out, struct svc_req *req) {
out->name = malloc(sizeof("foo"));
strcpy(out->name, "foo");
printf("Value: '%s'\n", out->name);
return TRUE;
}
int
foo_prog_2_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) {
xdr_free(xdr_result, result);
return(1);
}
Here's the client. It creates a variable, passes in a pointer to that variable and then outputs the value:
// foo_client.c
#include "memory.h" /* for memset */
#include "foo.h"
#include "stdio.h"
#include "stdlib.h"
#include "rpc/pmap_clnt.h"
#include "string.h"
#include "memory.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include <unistd.h>
int
main (int argc,char **argv)
{
CLIENT *cl;
cl = clnt_create("127.0.0.1", FOO_PROG, FOO_VERS, "tcp");
if (cl == NULL) {
clnt_perror(cl, "call failed");
exit (1);
}
foo_out out;
if (foo_2(&out, cl) != RPC_SUCCESS) {
printf("failed \n");
// exit(1);
}
printf("foo out: %s\n", out.name);
sleep(1);
exit(0);
}
When I run this, the server is fine I see Value: 'foo' every time it is called via the client. However the client crashes with a segv. Using address sanitizer I'm getting this:
=================================================================
==8269==ERROR: AddressSanitizer: SEGV on unknown address 0x0000004b0503 (pc 0x7fc9e2b5160f bp 0x000000000003 sp 0x7ffe264190c0 T0)
#0 0x7fc9e2b5160e in xdr_string (/lib/x86_64-linux-gnu/libc.so.6+0x13b60e)
#1 0x460751 in __interceptor_xdr_string.part.268 (/vagrant/foo/foo_client+0x460751)
#2 0x4b04a7 in xdr_foo_out /vagrant/foo/foo_xdr.c:13
#3 0x7fc9e2b4b3ea (/lib/x86_64-linux-gnu/libc.so.6+0x1353ea)
#4 0x4b03b8 in foo_2 /vagrant/foo/foo_clnt.c:15
#5 0x4b042e in main /vagrant/foo/foo_client.c:28
#6 0x7fc9e2a3682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#7 0x405298 in _start (/vagrant/foo/foo_client+0x405298)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 xdr_string
==8269==ABORTING
When I use GDB to inspect the contents of the struct before and after thefoo_2 call, it hasn't changed. It looks like the server didn't modify the value at all.
Question: How do you modify a struct with a string using multithreaded RPC calls? If I change my example to use an integer instead of a string, it works fine. So it seems like i'm missing something basic. Any ideas on what i'm doing wrong or steps to take to debug this?
In your client try allocating memory for the foo_out struct:
foo_out *out = malloc(sizeof(foo_out));
if (foo_2(out, cl) != RPC_SUCCESS) {
printf("failed \n");
// exit(1);
}
printf("foo out: %s\n", out->name);
I'm testing the execvpe() in c, I tried the below code, which cause the error as "implicit declaration of function 'execvpe' is invalid in C99 [-Wimplicit-function-declaration]".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _GNU_SOURCE
#include <unistd.h>
int main(int argc, char const *argv[])
{
//execl("/bin/echo", "echo", "Hello, world", NULL);
char *path = getenv("PATH");
char pathenv[strlen(path) + sizeof("PATH=")];
sprintf(pathenv, "PATH=%s", path);
char *envp[] = {pathenv, NULL};
char *tests[] = {"ls", "-lR", NULL};
execvpe(tests[0], tests, envp);
fprintf(stderr, "failed to execute \"%s\"\n", tests[0]);
return 0;
}
Then I test this code as below to test the existing status (which I copied from Compiler warnings for execvpe function, this time no error. Is there anyone can help me to figure out what's wrong in my above code? Thanks!
#include <unistd.h>
extern int execvpe(const char *file, char *const argv[], char *const envp[]);
Move the #define _GNU_SOURCE directive to before any of the #include directives, e.g.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
In Glibc, all of these headers pull in features.h which sets various macros based on the setting of _XOPEN_SOURCE, _POSIX_SOURCE, _GNU_SOURCE, etc. At the time of the first include, it is not set. When you get down to unistd.h, features.h has already been included and won't be applied again.
I looked into the "dpkg-query" source-code and tried to get the list of installed packages.
It compiles, but when i try to run i get the fault at modstatdb_open() function.
#define LIBDPKG_VOLATILE_API 1
#include <stdio.h>
#include <unistd.h>
#include <dpkg/macros.h>
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>
#include <dpkg/pkg-array.h>
#include <dpkg/debug.h>
#include <dpkg/pkg-list.h>
void main()
{
struct pkg_array array;
modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
pkg_array_init_from_db(&array);
printf("%d\n",array.n_pkgs);
pkg_array_destroy(&array);
modstatdb_shutdown();
}
Segmentation fault (core dumped)
What is wrong there?
Working version.
It has to use dpkg_program_init(char *progname); before all.
#define LIBDPKG_VOLATILE_API 1
#include <stdio.h>
#include <unistd.h>
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>
#include <dpkg/pkg-array.h>
void main()
{
struct pkgset *set;
struct pkginfo *inf;
struct pkg_array array;
dpkg_program_init("a.out");
modstatdb_open(msdbrw_available_readonly);
pkg_array_init_from_db(&array);
printf("Number of packages in local database: %d\n",array.n_pkgs);
inf = pkg_db_find_singleton("kate");
printf("status code of package: %d\n", inf->status);// 7 means installed
dpkg_program_done();
}
I have a really weird problem here, and haven't managed to find an answer online.
It appears after debugging with printf statements that a segfault ocurred when trying to read errno. Commenting problemed lines out one by one as they cause segfault resulted in having to comment out every reference to errno, after a readdir() call reaches the end of the directory stream and returns NULL.
Even then, the code then segfaults later when trying to access another automatic variable, file_count.
What is going on? Is this a stack overflow? How do I make it stop?
The code is below, if you feel the need to wade through it. All the problematic references to errno are removed, and the program segfaults after successfully executing the third second last line: printf("printing file_count\n");.
EDIT1: Here's a GDB backtrace:
#0 0xc95bf881 in strcpy () from /usr/lib/libc.so.1
#1 0x08051543 in dir_get_list (user=0x8047b88 "user1") at maildir.c:231
#2 0x08050f3e in main (argc=4, argv=0x80479f4) at maildir.c:43
END EDIT1
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#define MAX_FILENAME_LENGTH 255
#define MAX_USERNAME_LENGTH 40
#define MAX_PASSWORD_LENGTH 20
typedef int bool;
#define true 1
#define false 0
struct files_struct{
/*The number of email messages in a maildir.*/
int count;
/*A pointer to an array of pointers to the strings of the filenames. */
char **FileNames;
/*A pointer to an array of ints that give the corresponding size of the file.*/
int *FileSize;
};
typedef struct files_struct FilesStruct;
void dir_set_path(char* path);
bool check_user(char* username, char* pass);
FilesStruct* dir_get_list(char* user);
void delete_mail(char* user, char* filename);
char* get_file(char* user, char* filename);
FilesStruct* dir_get_list(char* user){
char maildir_name[MAX_FILENAME_LENGTH];
DIR * maildir_fd;
struct dirent *maildir_p;
strcpy(maildir_name,"./");
strncat(maildir_name,user,MAX_USERNAME_LENGTH);
strcat(maildir_name,"/");
if((pthread_mutex_lock(&maildir_root_mutex))<0)
perror("ERROR on locking maildir_root_mutex");
printf("Opening directory ""%s""\n",maildir_name);
if((maildir_fd = opendir(maildir_name))==NULL)
perror("ERROR on opendir");
int file_count = 0;
/* scan over entire directory, counting number of files to that data can be properly malloced */
while(1){
if((maildir_p = readdir(maildir_fd))==NULL){
closedir(maildir_fd);
printf("breaking loop\n");
break;
}
char file[MAX_FILENAME_LENGTH+1];
strcpy(file,maildir_p->d_name);
printf("File %d: '%s'\n",file_count+1,maildir_p->d_name);
/* if the file is a file other than an email */
if(!strcmp(".",file)||!strcmp("..",file)||!strcmp("pass",file)||!strcmp(".svn",file)){
printf("Continuing without incrementing file_count\n");
continue;
}
file_count++;
}
printf("%u\n",maildir_fd);
printf("printing file_count\n");
printf("%d",file_count);
printf("file_count printed successfully");
/* Additional code OMITTED */
I came across this recently. In my instance it was that another module had declared:
int errno = 0;
as a global, instead of #including errno.h. Any code that used the "proper" errno would immediately segfault.