Debugging: Add code to print backtrace for guest on SIGSEGV
[nativeclient.git] / intermodule_comm / nacl_imc_test_server.cc
blobe3f66ae67411fe4aff2e5ab10318db7d6648b71c
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // NaCl inter-module communication primitives.
35 // TODO: Make this program a unit test.
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include "native_client/intermodule_comm/nacl_imc.h"
44 nacl::SocketAddress server_address = {
45 "imc-server"
48 nacl::SocketAddress client_address = {
49 "imc-client"
52 namespace {
54 nacl::Handle g_front;
56 void CleanUp() {
57 nacl::Close(g_front);
60 // Writes the last error message to the standard error.
61 void PrintError(const char* message) {
62 char buffer[256];
64 if (nacl::GetLastErrorString(buffer, sizeof buffer) == 0) {
65 fprintf(stderr, "%s: %s\n", message, buffer);
69 } // namespace
71 int main() {
72 int result;
74 g_front = nacl::BoundSocket(&server_address);
75 if (g_front == nacl::kInvalidHandle) {
76 PrintError("BoundSocket");
77 exit(EXIT_FAILURE);
79 atexit(CleanUp);
81 // Test name collision.
82 nacl::Handle front2 = nacl::BoundSocket(&server_address);
83 assert(front2 == nacl::kInvalidHandle);
84 if (front2 == nacl::kInvalidHandle) {
85 PrintError("BoundSocket");
88 nacl::Handle handles[8];
89 nacl::MessageHeader header;
90 nacl::IOVec vec[3];
91 char buffer[64];
93 // Receive a handle connected to the client.
94 nacl::Handle client_handle = nacl::kInvalidHandle;
95 vec[0].base = buffer;
96 vec[0].length = sizeof buffer;
97 header.iov = vec;
98 header.iov_length = 1;
99 header.handles = handles;
100 header.handle_count = sizeof handles / sizeof handles[0];
101 result = nacl::ReceiveDatagram(g_front, &header, 0);
102 if (0 < result && header.handle_count == 1) {
103 client_handle = handles[0];
104 printf("%.*s: %d\n", result, buffer, client_handle);
105 } else {
106 PrintError("ReceiveDatagram");
107 exit(EXIT_FAILURE);
110 // Test kDontWait for a socket created by socketpair().
111 vec[0].base = buffer;
112 vec[0].length = sizeof buffer;
113 header.iov = vec;
114 header.iov_length = 1;
115 header.handles = NULL;
116 header.handle_count = 0;
117 result = nacl::ReceiveDatagram(client_handle, &header, nacl::kDontWait);
118 assert(result == -1);
119 PrintError("ReceiveDatagram");
120 assert(nacl::WouldBlock());
122 // Test an empty message.
123 vec[0].base = buffer;
124 vec[0].length = 0;
125 header.iov = vec;
126 header.iov_length = 1;
127 header.handles = NULL;
128 header.handle_count = 0;
129 result = nacl::SendDatagram(client_handle, &header, 0);
130 assert(result == 0);
132 // Test scatter/gather.
133 for (unsigned int i = 0; i < sizeof vec / sizeof vec[0]; ++i) {
134 buffer[i] = "ABC"[i];
135 vec[i].base = buffer + i;
136 vec[i].length = 1;
138 header.iov = vec;
139 header.iov_length = sizeof vec / sizeof vec[0];
140 header.handles = &client_handle;
141 header.handle_count = 1;
142 result = nacl::SendDatagram(client_handle, &header, 0);
143 assert(result == sizeof vec / sizeof vec[0]);
145 // Test Receive().
146 result = nacl::Receive(client_handle, buffer, sizeof buffer, 0);
147 if (result == -1) {
148 PrintError("ReceiveDatagram");
150 assert(result == 2);
151 if (0 < result) {
152 printf("%.*s\n", result, buffer);
155 // Test shared memory.
156 nacl::Handle shared_memory = nacl::CreateMemoryObject(1024 * 1024);
157 if (shared_memory != nacl::kInvalidHandle) {
158 void* shared_region = nacl::Map(0, 1024 * 1024,
159 nacl::kProtRead | nacl::kProtWrite,
160 nacl::kMapShared,
161 shared_memory, 0);
162 if (shared_region) {
163 memset(shared_region, 0, 1024 * 1024);
165 header.iov = vec;
166 header.iov_length = 2;
167 header.handles = &shared_memory;
168 header.handle_count = 1;
169 nacl::SendDatagram(client_handle, &header, 0);
171 memset(shared_region, 0xff, 1024 * 1024);
172 while (*static_cast<volatile unsigned int*>(shared_region) ==
173 0xffffffff) {
175 printf("server: shm ok.\n");
178 nacl::Unmap(shared_region, 1024 * 1024);
179 nacl::Close(shared_memory);
182 // Test kDontWait for a large message.
183 vec[0].base = buffer;
184 vec[0].length = sizeof buffer;
185 header.iov = vec;
186 header.iov_length = 1;
187 header.handles = NULL;
188 header.handle_count = 0;
189 result = nacl::ReceiveDatagram(client_handle, &header, nacl::kDontWait);
190 assert(result == sizeof buffer);
192 // Test close detection.
193 vec[0].base = buffer;
194 vec[0].length = sizeof buffer;
195 header.iov = vec;
196 header.iov_length = 1;
197 header.handles = NULL;
198 header.handle_count = 0;
199 result = nacl::ReceiveDatagram(client_handle, &header, 0);
200 assert(result <= 0);
202 nacl::Close(client_handle);
203 return 0;