0

I'm doing a client/server program with a multithreaded server and using sockets to communicate.

Everything works fine for the reading/sending part, but while doing some testing, I saw that the server exits when the read() function has nothing to read, instead of just waiting indefinitely.

It's not just the thread that stops, it's the whole program. Is it the normal behavior ? Shouldn't the read() function be blocking ?

Trying to do a minimal view of what I'm doing :

Server :

void admin_process_server(int sockcomm) // executed in a thread
{

char buff[256];
bzero(buff, sizeof(buff));

while(1){

    // definir le nombre de joueurs

    write_buff("NUMBER_OF_USERS", &buff);
    write(sockcomm, buff, sizeof(buff));

    read_client(&buff, sockcomm);
    printf("Message recu - Socket %d : %s, %ld\n", sockcomm, buff, strlen(buff));

    for (int p = 1; p <= GAME.nb_players; ++p)
    {

        write_buff("SET_USERNAME", &buff);
        write(sockcomm, buff, sizeof(buff));

        read_client(&buff, sockcomm);
        printf("Message recu - Socket %d : %s, %ld\n", sockcomm, buff, strlen(buff)); //exits here for some reasons ?

        set_player_username(p,strdup(buff));

    }
}
}

void read_client(char (*buff)[256], int sockfd)
{

    bzero(*buff, sizeof(*buff));
    int recu = read(sockfd, *buff, sizeof(*buff));
    (*buff)[recu] = '\0';

}

void set_player_username(int p, char * u)
{

    pthread_mutex_lock(&verrou_player);
    GAME.players[p].username = u;
    pthread_mutex_unlock(&verrou_player);

}

And basically, at the read() it exits, the client doesn't send nothing

Valgrind gives me this :

==4759== 
==4759== Process terminating with default action of signal 13 (SIGPIPE)
==4759==    at 0x4E4D2B7: write (write.c:27)
==4759==    by 0x10962C: admin_process_server (in /home/seitnom/Documents/ESGI/ProgSysRes/_______PROJECT/Server/server)
==4759==    by 0x10927C: th_action (in /home/seitnom/Documents/ESGI/ProgSysRes/_______PROJECT/Server/server)
==4759==    by 0x4E436DA: start_thread (pthread_create.c:463)
==4759==    by 0x517C88E: clone (clone.S:95)
==4759== 
==4759== HEAP SUMMARY:
==4759==     in use at exit: 389 bytes in 5 blocks
==4759==   total heap usage: 6 allocs, 1 frees, 1,413 bytes allocated
==4759== 
==4759== LEAK SUMMARY:
==4759==    definitely lost: 0 bytes in 0 blocks
==4759==    indirectly lost: 0 bytes in 0 blocks
==4759==      possibly lost: 285 bytes in 2 blocks
==4759==    still reachable: 104 bytes in 3 blocks
==4759==         suppressed: 0 bytes in 0 blocks
==4759== Rerun with --leak-check=full to see details of leaked memory
==4759== 
==4759== For counts of detected and suppressed errors, rerun with: -v
==4759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

After some deeper looking, the read() returns 0 (no idea why, there's nothing to read), and the program exits at the next send from the server.

Daycopo
  • 188
  • 1
  • 1
  • 11
  • 2
    Would you mind posting a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)? – MikeCAT Jun 19 '20 at 18:30
  • Complicate because I have a lot of code and functions on the side, but I tried to make it understandable – Daycopo Jun 19 '20 at 18:43
  • are you sure you do not have a crash for an other reason ? can you execute your program under *valgrind* to check memory usage ? – bruno Jun 19 '20 at 18:48
  • `for (int p = 1; p <= GAME.nb_players; ++p)` are you sure this is not off-by-one error? – MikeCAT Jun 19 '20 at 18:51
  • Maybe server receives some signal like broken pipe or sonething? See https://stackoverflow.com/questions/18935446/program-received-signal-sigpipe-broken-pipe – tstanisl Jun 19 '20 at 18:52
  • 2
    On error, read returns -1 and you write to buff[-1] – stark Jun 19 '20 at 18:54
  • @MikeCAT no it does 1,2,...,p – Daycopo Jun 19 '20 at 18:54
  • @MikeCAT wants to say in the `for` you call *set_player_username* doing `GAME.players[p].username` so you use index 1..n rather than 0..n-1. For an array of size N the valid index are from 0 up to N-1, not from 1 up to N – bruno Jun 19 '20 at 18:54
  • @bruno oh god okay that is a fatigue problem, fixed lol, but it shouldn't even get to a call, it should just block on the read() no ? Btw, added the valgrind results – Daycopo Jun 19 '20 at 18:58
  • @Daycopo look also at stark remark when read returns -1 – bruno Jun 19 '20 at 18:58
  • @stark yes but why does read() would return an error ? Shouldn't it wait for something to read ? In this case, at this point, the client literally sends nothing. Also, I dont get any Seg Fault – Daycopo Jun 19 '20 at 19:00
  • 1
    @Daycopo because the socket is closed on other side. Note to execute under *valgrind* compile in debug mode (-g) to have source filename and line indications – bruno Jun 19 '20 at 19:00
  • 1
    The Valgrind output appears to show the program terminating because of a signal before `read` is even called. – John Bollinger Jun 19 '20 at 19:00
  • thanks a lot all for the help ! – Daycopo Jun 19 '20 at 19:17

1 Answers1

2

According the valgind trace, your code is exiting at the write call, not at the read.

SIGPIPE means you are trying to write to a socket or pipe that has been closed at the other end. You can try to catch or ignore SIGPIPE if you want to something different from just exiting -- if you ignore SIGPIPE, then the write system call will return an EPIPE error.

In general your code looks very fragile as you are not checking the return values of the read and write systems calls for errors or other unusual conditions. So any unusual occurance will cause your program to misbehave and do something odd.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226