virtual int svc (void) { ACE_Thread_ID id; thread_id_ = id; while (1) { ACE_Message_Block *mb = 0; if (this->getq (mb) == -1) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("getq"))); if (mb->msg_type () == ACE_Message_Block::MB_HANGUP) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) Shutting down\n"))); mb->release (); break; } // Process the message. process_message (mb); // Return to work. this->manager_->return_to_work (this); } return 0; }
void Server_Handler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result) { if (!result.success ()) { errno = result.error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) Server handle %d: %p\n"), this->stream_.handle (), ACE_TEXT ("read"))); delete this; return; } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Server %@ handle %d recv %B of %B bytes\n"), this, this->stream_.handle (), result.bytes_transferred (), result.bytes_to_read ())); if (result.bytes_transferred () == 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Server handle %d closed by peer\n"), this->stream_.handle ())); delete this; return; } // Scan through the received data for the expected string. There may be // multiples and/or partials. Count up how many arrive before the connection // is closed. // Remember that the client side sends the terminating nul; in case the // whole thing didn't arrive, we add a nul to the end of the receive // block so we don't run off the end. When the recv into this buffer was // initiated, we left the last byte empty to facilitate this. ACE_Message_Block &b = result.message_block (); *(b.wr_ptr ()) = '\0'; size_t test_string_len = ACE_OS::strlen (test_string); while (b.length () >= test_string_len) { if (0 != ACE_OS::strncmp (b.rd_ptr (), test_string, test_string_len)) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) Read string: %C; expected: %C\n"), b.rd_ptr (), test_string)); b.rd_ptr (test_string_len); // That ran up over the string; can we also consume the nul? if (b.length () > 0) b.rd_ptr (1); ++this->msgs_rcvd_; } b.crunch (); if (this->stream_.read (b, b.space () - 1) == -1) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) Server_Handler: %p\n"), ACE_TEXT ("read"))); delete this; } return; }
int Worker_Task::svc (void) { // The <ACE_Task::svc_run()> method automatically adds us to the // process-wide <ACE_Thread_Manager> when the thread begins. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting svc() method\n"))); // Keep looping, reading a message out of the queue, until we get a // message with a length == 0, which signals us to quit. for (int count = 0; ; count++) { ACE_Message_Block *mb = 0; if (-1 == this->msg_queue ()->dequeue_head (mb)) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Worker_Task dequeue_head"))); size_t length = mb->length (); // If there's a next() Task then "logically" copy the message by // calling <duplicate> and send it on down the pipeline. Note // that this doesn't actually make a copy of the message // contents (i.e., the Data_Block portion), it just makes a copy // of the header and reference counts the data. if (this->next () != 0) { if (-1 == this->put_next (mb->duplicate ())) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Worker_Task put_next"))); } // If there's no next() Task to send to, then we'll consume the // message here. else if (length > 0) { int current_count = ACE_OS::atoi ((ACE_TCHAR *)(mb->rd_ptr ())); int i; if (count != current_count) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) count from block should be %d ") ACE_TEXT ("but is %d\n"), count, current_count)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) enqueueing %d duplicates\n"), current_count)); ACE_Message_Block *dup; // Enqueue <current_count> duplicates with msg_priority == 1. for (i = current_count; i > 0; i--) { ACE_ALLOCATOR_RETURN (dup, mb->duplicate (), -1); // Set the priority to be greater than "normal" // messages. Therefore, all of these messages should go // to the "front" of the queue, i.e., ahead of all the // other messages that are being enqueued by other // threads. dup->msg_priority (ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY + 1); int enqueue_prio_result = this->msg_queue ()->enqueue_prio (dup, // Don't block indefinitely if we flow control... (ACE_Time_Value *) &ACE_Time_Value::zero); if (enqueue_prio_result == -1) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) Pass %d %p\n"), i, ACE_TEXT ("Worker_Task enqueue_prio"))); } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) dequeueing %d duplicates\n"), current_count)); // Dequeue the same <current_count> duplicates. for (i = current_count; i > 0; i--) { if (-1 == this->msg_queue ()->dequeue_head (dup)) ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%t) Dup %d, %p\n"), i, ACE_TEXT ("Worker_Task dequeue dups"))); if (count != ACE_OS::atoi ((ACE_TCHAR *)(dup->rd_ptr ()))) ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) line %l, Dup %d, block's count ") ACE_TEXT ("is %d but should be %d\n"), i, ACE_OS::atoi ((ACE_TCHAR *)(dup->rd_ptr ())), count)); if (0 != ACE_OS::strcmp ((ACE_TCHAR *)mb->rd_ptr (), (ACE_TCHAR *)dup->rd_ptr ())) ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) Dup %d text is %s; ") ACE_TEXT ("should be %s\n"), i, dup->rd_ptr (), mb->rd_ptr ())); if (dup->msg_priority () != ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY + 1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) Dup %d block priority is %u; ") ACE_TEXT ("should be %u\n"), i, (unsigned int)dup->msg_priority (), (unsigned int)(ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY + 1))); dup->release (); } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) in iteration %d, length = %B, prio = %d, text = \"%*s\"\n"), count, length, mb->msg_priority (), (int)(length - 2), // remove the trailing "\n\0" mb->rd_ptr ())); } // We're responsible for deallocating this. mb->release (); if (length == 0) { //FUZZ: disable check_for_NULL ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) in iteration %d, queue len = %B, got NULL message, exiting\n"), count, this->msg_queue ()->message_count ())); //FUZZ: enable check_for_NULL break; } } // Note that the ACE_Task::svc_run () method automatically removes // us from the Thread_Manager when the thread exits. return 0; }
static int spawn (int proto) { ACE_SOCK_Dgram server_dgram; ACE_INET_Addr server_addr; if (proto == AF_INET) { server_addr.set (SERVER_PORT, ACE_LOCALHOST, 1, proto); } #if defined (ACE_HAS_IPV6) else { server_addr.set (SERVER_PORT, ACE_IPV6_LOCALHOST, 1, proto); } #endif /* ACE_HAS_IPV6 */ // Bind UDP server to the appropriate port if (server_dgram.open (server_addr, proto) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("server dgram open")), 1); } else { if (server_addr.get_port_number() != SERVER_PORT) { ACE_TCHAR hostname_string[100]; server_addr.addr_to_string (hostname_string, 100); ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT("(%P|%t) Portnumber has unexpected value of %d on host %s\n"), server_addr.get_port_number(), hostname_string), 1); } else { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) started server at proto %d, port %d\n"), proto, server_addr.get_port_number ())); #if !defined (ACE_LACKS_FORK) switch (ACE_OS::fork (ACE_TEXT ("child"))) { case -1: ACE_ERROR_BREAK ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("fork failed"))); /* NOTREACHED */ case 0: client (&server_addr); ACE_OS::exit (0); /* NOTREACHED */ default: server ((void *) &server_dgram); ACE_OS::wait (); } #elif defined (ACE_HAS_THREADS) if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (server), (void *) &server_dgram, THR_NEW_LWP | THR_DETACHED) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("thread create failed")), 1); if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (client), (void *) &server_addr, THR_NEW_LWP | THR_DETACHED) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("thread create failed")), 1); // Wait for the threads to exit. ACE_Thread_Manager::instance ()->wait (); #else ACE_ERROR ((LM_INFO, ACE_TEXT ("(%P|%t) ") ACE_TEXT ("only one thread may be run ") ACE_TEXT ("in a process on this platform\n"))); #endif /* ACE_HAS_THREADS */ } server_dgram.close (); } return 0; }