corrupted strings passed by FIFO (named pipes)

[Mac OS X, Xcode 6.6.1]
I'm communicating between two separate processes using FIFOs (named pipes). I've greatly simplified the code for this forum, so that the "command" is a simple string that the server changes to upper case before sending it back.

Problems: When the client sends a short string like "abcdefg" the server sees a garbage character (upside-down "?") in place of the last char, and for long strings the whole string turns into garbage.

I've tried adding 1 to the char count in "write" and using an array of chars in place of the strings in "write". Neither helped. Any ideas?

The output for two cases, the only difference being the length of the string sent by the client ("?" inverted for visibility):

<client>
Trying to connect to server.
Sending 'abcdefg' to server.
Connection succeeded.
The reply was: ABCDEF?
Program ended with exit code: 0


<server>
Making fifos for send & rcv
Opening communications w/ client.
The input_string is:
abcdef?
The output_string is:
ABCDEF?


-----------------------

<client>
Trying to connect to server.
Sending 'abcdefghijklmnopqrstuvwxyz' to server.
Connection succeeded.
The reply was: ??????????????????????????
caseclient(43047,0x7fff72b37310) malloc: *** error for object 0x100104360: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
(lldb)


<server>
Making fifos for send & rcv
Opening communications w/ client.
The input_string is:
??????????????????????????
The output_string is:
??????????????????????????


Here is the server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <string>
#include <iostream>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <algorithm>

#define FIFO_FROM_SERVER  "/tmp/fifo_to_client"
#define FIFO_TO_SERVER  "/tmp/fifo_from_client"

using namespace std;


struct raise_case {
    int operator() ( int ch )
    {
        return std::toupper ( ch );
    }
};

int main( int argc, const char * argv[] )
{
    //- server -
    // Get string from client and change to UPPER CASE; then send it back
    
    int res, out_pipe, in_pipe;
    
    std::string input_string, output_string;
    
    std::cout << "Making fifos for send & rcv" << "\n";
    // - server- make the FIFOs if not done already
    if (access(FIFO_FROM_SERVER, F_OK) == -1) {
        res = mkfifo(FIFO_FROM_SERVER, 0666);
        if (res != 0) {
            fprintf(stderr, "Could not create fifo %s\n",
                    FIFO_FROM_SERVER);
            exit(1);
        }
        
        if (access(FIFO_TO_SERVER, F_OK) == -1) {
            res = mkfifo(FIFO_TO_SERVER, 0666);
            if (res != 0) {
                fprintf(stderr, "Could not create fifo %s\n",
                        FIFO_TO_SERVER);
                exit(1);
            }
        }
    }
    
    printf("Opening communications w/ client.\n");
    if( (out_pipe = open(FIFO_FROM_SERVER, O_WRONLY )) < 1 ) {
        perror("Error: open( ): ");
        return 1;
    }
    
    do
    {
        // Wait for a request from the client.
        const int MAX_READ_CHARS = 800;
        if( (in_pipe = open(FIFO_TO_SERVER, O_RDONLY )) < 1 ) {
            perror("Error: open( ): ");
            return 1;
        }
        
        
        if( read( in_pipe, &input_string, MAX_READ_CHARS ) < 0 ) {
            perror("Error: read( ): ");
            return 1;
        }
        
        // Got a request from client.
        std::cout << "The input_string is: \n" << input_string << "\n";
        
        output_string = input_string;
        // Capitalize all the letters and send back to client
        std::transform(output_string.begin(), output_string.end(), output_string.begin(), raise_case());

        std::cout << "The output_string is: \n" << output_string << "\n";

            if( write( out_pipe, &output_string,  output_string.length() ) < 0 ) {
                perror("Error: write( ): ");
                return 1;
            }
        
        close( in_pipe );
        }
    
    while (true);
    
    return 0;
}


Here's the client:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

//
//  main.cpp
//  testclient
//

#include <unistd.h>
#include <iostream>
#include <fcntl.h>
#include <chrono>

#define FIFO_FROM_SERVER  "/tmp/fifo_to_client"
#define FIFO_TO_SERVER  "/tmp/fifo_from_client"

int main( int argc, const char* argv[] ) {
    
    
    int  in_pipe, out_pipe, reply_size = 500;
    std::string command, reply;
    
    if (argc == 2) {
        command = argv[1];
    }
    else  {
        command = "test";
    }
    
    printf("Trying to connect to server.\n");
    if( (in_pipe = open(FIFO_FROM_SERVER, O_RDONLY, 0 )) == -1 ) {
        perror("Error: open( ): ");
        return 1;
    }
    
    if( (out_pipe = open(FIFO_TO_SERVER, O_WRONLY, 0 )) == -1 ) {
        perror("Error: open( ): ");
        return 1;
    }
    
    std::cout << "Sending '" << command << "' to server." << std::endl;
    
    // Send a command to server
    if( write( out_pipe, &command, command.length() ) < 0 ) {
        perror("Error: write( ): ");
        return 1;
    }
    
    close( out_pipe );

    // Wait for reply
    
    errno = 0;
    long chars_read = read( in_pipe, &reply, reply_size );
    if( chars_read < 0 ) {
        perror("Error: read( ): ");
        return 1;
    }
    
    printf("Connection succeeded.\n");
    std::cout << "The reply was: " << reply << std::endl;
    
    close( in_pipe );
    return 0;
}


Thanks for any help- Scott
OK, I fixed the simpler problem, replacement of the last char by "?", by adding 1 to the last param of the write statements, the length. I thought I had tried that, but I guess not. I guess it has to include the null character.

The second problem, longer strings causing complete loss of the original string and a malloc error, remains.
You cannot read/write a string like that. You read/write data members of the class not the data itself.

Like so:
if( write( out_pipe, command.c_str(), command.length() + 1) < 0 )

read requires a buffer:
1
2
3
char buf[1024];

long chars_read = read( in_pipe, buf, sizeof(buf) );
All fixed! Thank you very much for the expert advice.
Topic archived. No new replies allowed.