Changeset 45
- Timestamp:
- 06/30/08 11:57:16 (5 months ago)
- Files:
-
- trunk/libsipc/include/sipc/sipc.h (modified) (3 diffs)
- trunk/libsipc/man/man3/sipc_ioctl.3 (added)
- trunk/libsipc/man/man3/sipc_open.3 (modified) (2 diffs)
- trunk/libsipc/man/man3/sipc_recv_data.3 (modified) (3 diffs)
- trunk/libsipc/src/libsipc.map (modified) (1 diff)
- trunk/libsipc/src/sipc.c (modified) (2 diffs)
- trunk/libsipc/src/sipc_internal.h (modified) (1 diff)
- trunk/libsipc/src/sipc_mqueue.c (modified) (7 diffs)
- trunk/libsipc/src/sipc_shm.c (modified) (2 diffs)
- trunk/libsipc/tests/mqueue.c (modified) (4 diffs)
- trunk/libsipc/tests/shm.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libsipc/include/sipc/sipc.h
r41 r45 40 40 #define SIPC_NUM_TYPES 2 41 41 42 /* SIPC behaviors, for sipc_ioctl() */ 43 #define SIPC_BLOCK 0 44 #define SIPC_NOBLOCK 1 45 42 46 /* sipc_open(char *key, int role, int ipc_type, size_t size) 43 47 * key Unique key to identify IPC communication channel, … … 62 66 void sipc_unlink(const char *key, int ipc_type); 63 67 68 /* Modify the behavior of an open SIPC channel. Returns 0 on success, 69 * <0 on failure. 70 */ 71 int sipc_ioctl(sipc_t *sipc, int request); 72 64 73 /* Blocking call to send msglen bytes of data. 65 74 * This can only be called if sender was specified when sipc_init was called. … … 67 76 int sipc_send_data(sipc_t *sipc, int msg_len); 68 77 69 /* Blocking call to recieve data. Data will be allocated and filled and70 * len will be set to the length. Returns 0 on success, <0 on failure*/78 /* Call to receive data. Data will be allocated and filled and len 79 * will be set to the length. Returns 0 on success, <0 on failure. */ 71 80 int sipc_recv_data(sipc_t *sipc, char **data, int *len); 72 81 trunk/libsipc/man/man3/sipc_open.3
r38 r45 1 .\" Copyright (C) 2006 , 2007Tresys Technology, LLC1 .\" Copyright (C) 2006 - 2008 Tresys Technology, LLC 2 2 .\" This file is distributed according to the GNU Lesser General Public License 3 3 .TH "SIPC_OPEN" 3 "2006-08-10" "Linux 2.6" "Linux Programmer's Manual" … … 43 43 This function returns a pointer to the new IPC handle on success, NULL on error. 44 44 .SH "SEE ALSO" 45 \fBsipc_close(3)\fR, \fBsipc_unlink(3)\fR 45 \fBsipc_close(3)\fR, \fBsipc_unlink(3)\fR, \fBsipc_ioctl(3)\fR 46 46 .SH AUTHOR 47 47 David Windsor <dwindsor@tresys.com> trunk/libsipc/man/man3/sipc_recv_data.3
r40 r45 24 24 .TP 25 25 .I len 26 This will holdthe total number of bytes received26 Pointer to the total number of bytes received 27 27 .PP 28 28 If the IPC channel is a message queue, \fBsipc_recv_data\fR() … … 41 41 \fBsipc_recv_data\fR(), else undefined behavior results. 42 42 .P 43 This function blocks if no data is in the IPC channel. 43 By default, this function blocks if no data is in the IPC channel. 44 This can be changed to non-blocking via \fBsipc_ioctl()\fR. 44 45 .SH "RETURN VALUE" 45 This function returns 0 on success, \-1 on error. 46 Upon error, 46 This function returns 0 on success. On error, \-1 is returned, 47 47 .I *data 48 will be set to NULL and48 will be set to NULL, 49 49 .I msg_len 50 will be set to zero. 50 will be set to zero, and \fIerrno\fR is set appropriately. 51 .SH "ERRORS" 52 .TP 53 .B EAGAIN 54 The channel is set to non-blocking and nothing was available to be 55 read. 56 .TP 57 .B EBADF 58 The channel is not open for receiving. 59 .TP 60 .B EIO 61 Message was corrupted during transmission, and is now lost. 51 62 .SH "EXAMPLES" 52 63 .nf … … 61 72 .fi 62 73 .SH "SEE ALSO" 63 \fBsipc_send_data(3)\fR, \fBsipc_shm_recv_done(3)\fR 74 \fBsipc_send_data(3)\fR, \fBsipc_shm_recv_done(3)\fR, \fBsipc_ioctl(3)\fR 64 75 .SH AUTHOR 65 76 David Windsor <dwindsor@tresys.com> trunk/libsipc/src/libsipc.map
r44 r45 11 11 local: *; 12 12 }; 13 14 VERS_1.1{ 15 global: 16 sipc_ioctl; 17 }; trunk/libsipc/src/sipc.c
r41 r45 53 53 new_sipc->ipc_type = ipc_type; 54 54 new_sipc->role = role; 55 new_sipc->non_blocking = 0; 55 56 new_sipc->len = len; 56 57 new_sipc->msg_len = SIPC_MSGLEN_NOT_SET; … … 116 117 } 117 118 119 int sipc_ioctl(sipc_t *sipc, int request) 120 { 121 if (!sipc) { 122 errno = EINVAL; 123 return -1; 124 } 125 126 switch (request) { 127 case SIPC_BLOCK: 128 sipc->non_blocking = 0; 129 break; 130 case SIPC_NOBLOCK: 131 sipc->non_blocking = IPC_NOWAIT; 132 break; 133 default: 134 errno = EINVAL; 135 return -1; 136 } 137 return 0; 138 } 139 118 140 char *sipc_get_data_ptr(sipc_t *sipc) 119 141 { trunk/libsipc/src/sipc_internal.h
r44 r45 76 76 int ipc_type; 77 77 int role; 78 int non_blocking; /* set to IPC_NOWAIT if reads should be 79 nonblocking, 0 to block (default) */ 78 80 union 79 81 { trunk/libsipc/src/sipc_mqueue.c
r44 r45 193 193 int retv = -1, alloc_sz = 0, idx = 0, recv_sz; 194 194 int msgtxt_sz = SIPC_MQUEUE_MSG_SZ - sizeof(struct msgbuf); 195 196 if (!sipc || !data || !len) 195 int error = 0; 196 197 if (data) 198 *data = NULL; /* Pointer to a buffer created here */ 199 if (len) 200 *len = 0; /* Bytes received so far */ 201 if (!sipc || !data || !len) { 202 error = EINVAL; 197 203 goto err; 198 199 *data = NULL; /* Pointer to a buffer created here */ 204 } 205 200 206 idx = 0; /* Current index into the buffer */ 201 *len = 0; /* Bytes received so far */202 207 203 208 if (sipc->role != SIPC_RECEIVER) { 209 error = EBADF; 204 210 sipc_error(sipc, "sipc_send_data called without receiver flag enabled in IPC structure\n"); 205 211 goto err; … … 212 218 /* Receive and validate the length of message marker */ 213 219 if (sipc->msg_len == SIPC_MSGLEN_NOT_SET) { 214 if (msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, 0) < 0) { 215 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 216 goto err; 217 } 218 if (is_end_xmit(mbuf)) 220 if (msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, sipc->non_blocking) < 0) { 221 error = errno; 222 if (error == ENOMSG || error == EAGAIN) 223 error = EAGAIN; 224 else 225 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 226 goto err; 227 } 228 if (is_end_xmit(mbuf)) { 229 errno = 0; 219 230 return 0; 231 } 220 232 221 233 if (is_msg_len(mbuf)) { 222 234 sipc->msg_len = atoi(mbuf->mtext); 223 235 if (sipc->msg_len < 0) { 236 error = EIO; 224 237 sipc_error(sipc, "libsipc: bad message length\n"); 225 238 goto err; 226 239 } 227 240 if (sipc->msg_len > sipc->len) { 241 error = EIO; 228 242 sipc_error(sipc, "libsipc: cannot receive buffer of size %zd, can only receive %zd\n", 229 243 sipc->msg_len, sipc->len); … … 231 245 } 232 246 } else { 247 error = EIO; 233 248 sipc_error(sipc, "libsipc: did not receive length of message, received %ld\n", mbuf->mtype); 234 249 goto err; … … 239 254 * Stop when we have received the total number of bytes 240 255 * or upon receiving the end of message marker. */ 241 if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, 0)) < 0) { 242 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 256 if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, sipc->non_blocking)) < 0) { 257 error = errno; 258 if (error == ENOMSG || error == EAGAIN) 259 error = EAGAIN; 260 else 261 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 243 262 goto err; 244 263 } … … 253 272 char *tdata = realloc(*data, alloc_sz); 254 273 if (!tdata) { 274 error = errno; 255 275 sipc_error(sipc, "%s\n", "Out of memory"); 256 free(*data);257 *data = NULL;258 *len = 0;259 276 goto err; 260 277 } … … 266 283 267 284 /* Receive the next message */ 268 if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, 0)) < 0) { 269 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 270 free(*data); 271 *data = NULL; 272 *len = 0; 285 if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ - sizeof(long), SIPC_ANY, sipc->non_blocking)) < 0) { 286 error = errno; 287 if (error == ENOMSG || error == EAGAIN) 288 error = EAGAIN; 289 else 290 sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 291 /* Note that it is possible for a non-blocking 292 * SIPC to fail while receiving a chunked message, 293 * in which case the entire message becomes lost. 294 * This is probably not the best design possible. 295 */ 273 296 goto err; 274 297 } … … 278 301 err: 279 302 sipc->msg_len = SIPC_MSGLEN_NOT_SET; /* Unset message length */ 303 errno = error; 304 if (retv) { 305 free(*data); 306 *data = NULL; 307 *len = 0; 308 } 280 309 return retv; 281 310 } trunk/libsipc/src/sipc_shm.c
r43 r45 188 188 /* Receive a DATA_READY marker from sender and pass the shm pointer to 189 189 * the caller. This function will block if there is nothing on the 190 * message queue .190 * message queue, if the handle is set to blocking mode (default). 191 191 */ 192 192 int sipc_shm_recv_data(sipc_t *sipc, char **data, int *len) 193 193 { 194 194 int mtype = 0; 195 196 if (!sipc || !data || !len) 197 return -1; 198 199 *data = NULL; 200 *len = 0; 195 int block; 196 197 if (data) 198 *data = NULL; /* Pointer to a buffer created here */ 199 if (len) 200 *len = 0; /* Bytes received so far */ 201 if (!sipc || !data || !len) { 202 errno = EINVAL; 203 return -1; 204 } 205 block = (sipc->non_blocking == 0 ? 1 : 0); 201 206 202 207 /* Get a message from the side channel. */ 203 mtype = mqueue_get_msg_type(sipc->s.msqid, SIPC_ANY, MQ_BLOCK);208 mtype = mqueue_get_msg_type(sipc->s.msqid, SIPC_ANY, block); 204 209 if (mtype == SIPC_DATA_READY) { 205 210 /* It is now OK to read shared memory */ … … 208 213 return 0; 209 214 } else { 210 sipc_error(sipc, "Received a message of unknown type\n"); 211 return -1; 212 } 213 } 215 int error = errno; 216 if (error == ENOMSG || error == EAGAIN) 217 errno = EAGAIN; 218 else { 219 errno = error; 220 sipc_error(sipc, "Received a message of unknown type\n"); 221 } 222 return -1; 223 } 224 } trunk/libsipc/tests/mqueue.c
r39 r45 48 48 static void do_parent_chunked(void); 49 49 static void do_child_chunked(void); 50 static void do_blocked_parent(void); 51 static void do_blocked_child(void); 50 52 static int verify_data(char *filename, char *recv_data); 51 53 static inline int is_end_xmit(char *data); … … 229 231 } 230 232 233 static void test_blocked_mqueue(void) 234 { 235 pid_t pid; 236 int status = 0; 237 238 switch ((pid = fork())) { 239 case -1: 240 fprintf(stderr, "fork: %s\n", strerror(errno)); 241 return; 242 case 0: 243 sipc_close(reader2_ipc); 244 do_blocked_child(); 245 exit(0); 246 break; 247 default: 248 do_blocked_parent(); 249 break; 250 } 251 252 wait(&status); 253 } 254 231 255 CU_TestInfo mqueue_tests[] = { 232 256 {"unforked mqueue", test_unforked_mqueue} … … 235 259 , 236 260 {"forked chunked mqueue", test_chunked_mqueue} 261 , 262 {"forked blocked mqueue", test_blocked_mqueue} 237 263 , 238 264 CU_TEST_INFO_NULL … … 341 367 } 342 368 369 /* 370 * Test blocking and non-blocking mode. 371 */ 372 static void do_blocked_child(void) 373 { 374 char *shm_data = sipc_get_data_ptr(writer_ipc); 375 if (!shm_data) { 376 sipc_error(writer_ipc, "Unable to get pointer to data.\n"); 377 return; 378 } 379 sleep(2); 380 shm_data[0] = 0x42; 381 if (sipc_send_data(writer_ipc, 1) < 0) { 382 sipc_error(writer_ipc, "Unable to send data\n"); 383 return; 384 } 385 sleep(2); 386 shm_data[0] = 0x43; 387 if (sipc_send_data(writer_ipc, 1) < 0) { 388 sipc_error(writer_ipc, "Unable to send data\n"); 389 return; 390 } 391 shm_data[0] = 0x44; 392 if (sipc_send_data(writer_ipc, 1) < 0) { 393 sipc_error(writer_ipc, "Unable to send data\n"); 394 return; 395 } 396 sipc_close(writer_ipc); 397 } 398 399 static void do_blocked_parent(void) 400 { 401 char *data = NULL; 402 int len = 0, retv, error; 403 404 printf("This should pause for 2 seconds (default read)...\n"); 405 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 406 CU_FAIL("Error during first read"); 407 } 408 CU_ASSERT(len == 1 && data[0] == 0x42); 409 free(data); 410 411 printf("No blocking here.\n"); 412 CU_ASSERT(sipc_ioctl(reader_ipc, SIPC_NOBLOCK) == 0); 413 retv = sipc_recv_data(reader_ipc, &data, &len); 414 error = errno; 415 CU_ASSERT(retv == -1); 416 CU_ASSERT(data == NULL); 417 CU_ASSERT(len == 0); 418 CU_ASSERT(error == EAGAIN); 419 420 printf("This should pause for 3 seconds... (non-blocking read)\n"); 421 sleep(3); 422 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 423 CU_FAIL("Error during first read"); 424 } 425 CU_ASSERT(len == 1 && data[0] == 0x43); 426 free(data); 427 428 CU_ASSERT(sipc_ioctl(reader_ipc, -1) < 0); 429 CU_ASSERT(sipc_ioctl(reader_ipc, SIPC_BLOCK) == 0); 430 431 printf("This should pause for 1 second... (blocked read)\n"); 432 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 433 CU_FAIL("Error during first read"); 434 } 435 CU_ASSERT(len == 1 && data[0] == 0x44); 436 free(data); 437 } 438 343 439 static int send_end_xmit(sipc_t *ipc) 344 440 { trunk/libsipc/tests/shm.c
r39 r45 46 46 static void do_binary_child(void); 47 47 static void do_binary_parent(void); 48 static void do_blocked_child(void); 49 static void do_blocked_parent(void); 48 50 static void send_end_xmit(sipc_t *sipc); 49 51 static int verify_data(char *filename, char *recv_data); … … 175 177 } 176 178 179 static void test_blocked_shm(void) 180 { 181 int status; 182 pid_t pid; 183 184 switch (pid = fork()) { 185 case -1: 186 fprintf(stderr, "fork: %s\n", strerror(errno)); 187 return; 188 case 0: 189 sipc_close(reader_ipc); 190 do_blocked_child(); 191 /* Exit here to prevent displaying results 2x */ 192 exit(0); 193 break; 194 default: 195 do_blocked_parent(); 196 break; 197 } 198 199 wait(&status); 200 } 201 177 202 CU_TestInfo shm_tests[] = { 178 203 {"forked shm", test_shm} 179 204 , 180 205 {"binary shm", test_binary_shm} 206 , 207 {"blocked shm", test_blocked_shm} 181 208 , 182 209 CU_TEST_INFO_NULL … … 313 340 } 314 341 342 /* 343 * Test blocking and non-blocking mode. 344 */ 345 static void do_blocked_child(void) 346 { 347 char *shm_data = sipc_get_data_ptr(writer_ipc); 348 if (!shm_data) { 349 sipc_error(writer_ipc, "Unable to get pointer to data.\n"); 350 return; 351 } 352 sleep(2); 353 shm_data[0] = 0x42; 354 if (sipc_send_data(writer_ipc, 1) < 0) { 355 sipc_error(writer_ipc, "Unable to send data\n"); 356 return; 357 } 358 sleep(2); 359 shm_data[0] = 0x43; 360 if (sipc_send_data(writer_ipc, 1) < 0) { 361 sipc_error(writer_ipc, "Unable to send data\n"); 362 return; 363 } 364 shm_data[0] = 0x44; 365 if (sipc_send_data(writer_ipc, 1) < 0) { 366 sipc_error(writer_ipc, "Unable to send data\n"); 367 return; 368 } 369 sipc_close(writer_ipc); 370 } 371 372 static void do_blocked_parent(void) 373 { 374 char *data = NULL; 375 int len = 0, retv, error; 376 377 printf("This should pause for 2 seconds (default read)...\n"); 378 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 379 CU_FAIL("Error during first read"); 380 } 381 CU_ASSERT(len == DATA_LEN && data[0] == 0x42); 382 sipc_shm_recv_done(reader_ipc); 383 384 printf("No blocking here.\n"); 385 CU_ASSERT(sipc_ioctl(reader_ipc, SIPC_NOBLOCK) == 0); 386 retv = sipc_recv_data(reader_ipc, &data, &len); 387 error = errno; 388 CU_ASSERT(retv == -1); 389 CU_ASSERT(data == NULL); 390 CU_ASSERT(len == 0); 391 CU_ASSERT(error == EAGAIN); 392 393 printf("This should pause for 3 seconds... (non-blocking read)\n"); 394 sleep(3); 395 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 396 CU_FAIL("Error during first read"); 397 } 398 CU_ASSERT(len == DATA_LEN && data[0] == 0x43); 399 sipc_shm_recv_done(reader_ipc); 400 401 CU_ASSERT(sipc_ioctl(reader_ipc, -1) < 0); 402 CU_ASSERT(sipc_ioctl(reader_ipc, SIPC_BLOCK) == 0); 403 404 printf("This should pause for 1 second... (blocked read)\n"); 405 if (sipc_recv_data(reader_ipc, &data, &len) < 0) { 406 CU_FAIL("Error during first read"); 407 } 408 CU_ASSERT(len == DATA_LEN && data[0] == 0x44); 409 sipc_shm_recv_done(reader_ipc); 410 } 411 315 412 static void send_end_xmit(sipc_t *sipc) 316 413 {
