-1

I have a program that get IP of list of domains in a txt a huge list like millions of domains by gethostbyname and put them in struct sockaddr_in and I use multithreading to make the process faster the check them all after working for 4 or 5 mintues i get segmentation fault exactly in the memcpy code

It is a linux code

Example of the main routine of all the threads:


#include <netdb.h>
#include <arpa/inet.h>


void* startcheckingdomains(){
    while(1){
        char* domain = "www.google.com";
        struct hostent* hp = gethostbyname(domain);
        struct sockaddr_in sockaddr;

        if(hp == NULL){
            herror("hp");
        }else{
            memcpy(&sockaddr.sin_addr,hp->h_addr,hp->h_length);
        }
    }
}

This is the error produced by gdb:

Thread 535 "main" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffe8f606700 (LWP 27402)]
__memmove_avx_unaligned_erms ()
  • Segfaults are usually easy to debug - use your debugger to see how you ended up at the crash (stack trace) and inspect program state (variable values etc in crashing stack frame as well as those leading up to the crash). See [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Jesper Juhl Nov 09 '22 at 02:17
  • `char* domain = "www.google.com";` --> `const char* domain = "www.google.com";` or `const auto domain = "www.google.com";` – Jesper Juhl Nov 09 '22 at 02:20
  • Don't use `NULL` in modern C++. Use [nullptr](https://en.cppreference.com/w/cpp/language/nullptr). – Jesper Juhl Nov 09 '22 at 02:21
  • 2
    Your function claims to return `void*` but doesn't actually return *anything* - that's [UB](https://en.cppreference.com/w/cpp/language/ub). – Jesper Juhl Nov 09 '22 at 02:23
  • `while(1){` with no `break`, `return`, `exit` or similar. That's an interesting infinite loop - again [UB](while(1){`. Also, why `while (1)` and not `while (true)`? C++ is *not* (old) C. – Jesper Juhl Nov 09 '22 at 02:26
  • @MrBen Check `hp->h_addrtype`, it may be AF_INET6, so `hp->h_length` is bigger than `struct sockaddr_in`. But better don't use `gethostbyname()`, it is deprecated. Use `getaddrinfo()` instead. – dimich Nov 10 '22 at 01:36

1 Answers1

1

The manual page for the function gethostbyname states the following:

The functions gethostbyname() and gethostbyaddr() may return pointers to static data, which may be overwritten by later calls.

This means that if you have several threads calling the function at the same time, they may be overwriting each other's data.

The manual also states:

Glibc2 also has reentrant versions [...] gethostbyname_r() [...]. The caller supplies a hostent structure ret which will be filled in on success, and a temporary work buffer buf of size buflen.

Therefore, if you are using glibc, the problem may disappear if you use the function gethostbyname_r instead of gethostbyname.

Alternatively, you may want to use the function getaddrinfo, which is also reentrant.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39