int DgramHandler::handle_timeout (const ACE_Time_Value ¤t_time, const void *act) { ACE_UNUSED_ARG (current_time); ACE_UNUSED_ARG (act); int sendBuffer = 0; if (++timeoutsTriggered_ >= expectedTriggers_) reactor ()->cancel_timer (this, 1); ACE_SOCK_Dgram socket; if (-1 == socket.open (ACE_INET_Addr (static_cast< u_short > (0), static_cast< ACE_UINT32 > (INADDR_ANY)), ACE_PROTOCOL_FAMILY_INET, 0, 1)) ACE_ERROR ((LM_ERROR, ACE_TEXT (" (%P) %p\n"), ACE_TEXT ("Cannot open socket for sending Qt dgrams"))); ACE_INET_Addr peerAddr; peer_.get_local_addr (peerAddr); if (sizeof (sendBuffer) != socket.send (&sendBuffer, sizeof (sendBuffer), peerAddr)) ACE_ERROR ((LM_ERROR, ACE_TEXT (" (%P) %p\n"), ACE_TEXT ("Cannot send dgram"))); else ++dgramsSent_; socket.close (); return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { parse_args (argc, argv); // Child process code. if (child_nr >= 0) { ACE_TCHAR lognm[MAXPATHLEN]; int mypid (ACE_OS::getpid ()); ACE_OS::sprintf(lognm, ACE_TEXT ("RW_Process_Mutex_Test-child-%d"), (int)mypid); ACE_START_TEST (lognm); if (child_nr == 0) writer (); else reader (child_nr); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT ("RW_Process_Mutex_Test")); // Although it should be safe for each process to construct and // destruct the rw lock, this can disturb other process still // using the lock. This is not really correct, and should be // looked at, but it gets things moving. // Also see Process_Mutex_Test.cpp for similar issue. ACE_RW_Process_Mutex mutex (mutex_name.c_str ()); // Make sure the constructor succeeded if (ACE_LOG_MSG->op_status () != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Parent, mutex %s %p\n"), mutex_name.c_str (), ACE_TEXT ("ctor"))); } #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) static const ACE_TCHAR* format = ACE_TEXT ("%ls -c %d -p %u -n %ls"); #else static const ACE_TCHAR* format = ACE_TEXT ("%s -c %d -p %u -n %s"); #endif /* !ACE_WIN32 && ACE_USES_WCHAR */ // The parent process reads time ranges sent from the children via // UDP. Grab an unused UDP port to tell the children to send to. ACE_INET_Addr me; ACE_SOCK_Dgram sock; if (sock.open (ACE_Addr::sap_any, PF_INET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Socket %p\n"), ACE_TEXT ("open")), -1); sock.get_local_addr (me); ACE_TCHAR me_str[80]; me.addr_to_string (me_str, 80); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Receiving on %s\n"), me_str)); // Spawn 1 writer and 3 reader processes that will contend for the // lock. Child writer; Child readers[Nr_Processes - 1]; int i; for (i = 0; i < Nr_Processes; i++) { Child *child = (i == 0 ? &writer : &readers[i-1]); ACE_Process_Options options; options.command_line (format, argc > 0 ? argv[0] : ACE_TEXT ("RW_Process_Mutex_Test"), i, (unsigned int)me.get_port_number (), mutex_name.c_str ()); if (child->spawn (options) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("spawn of child %d %p\n"), i, ACE_TEXT ("failed")), -1); } else { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child process %d has pid = %d.\n"), i, (int)(child->getpid ()))); } } // Keep reading time ranges reported from the children until all the // children have exited. Alternate between checking for a range and // checking for exits. int processes = Nr_Processes; Child *children[Nr_Processes]; for (i = 0; i < Nr_Processes; i++) children[i] = (i == 0 ? &writer : &readers[i-1]); Range_Report report; ACE_Time_Value poll (0); ACE_INET_Addr from; ssize_t bytes; while (processes > 0) { ACE_Time_Value limit (10); bytes = sock.recv (&report, sizeof (report), from, 0, &limit); if (bytes > 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Report from child %d; %b bytes\n"), report.child_, bytes)); if (report.child_ == 0) writer.add_range (report.range_); else { if (report.child_ >= 1 && report.child_ < Nr_Processes) readers[report.child_ - 1].add_range (report.range_); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Report from out-of-range child #%d\n"), report.child_)); } } else { if (errno == ETIME) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("UDP time out; check child exits\n"))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("UDP recv"))); } for (i = 0; i < Nr_Processes; i++) { if (children[i] == 0) continue; ACE_exitcode child_status; // See if the child has exited. int wait_result = children[i]->wait (poll, &child_status); if (wait_result == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Wait for child %d, %p\n"), i, ACE_TEXT ("error"))); else if (wait_result != 0) { if (child_status == 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child %d finished ok\n"), (int)(children[i]->getpid ()))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Child %d finished with status %d\n"), (int)(children[i]->getpid ()), child_status)); children[i] = 0; --processes; } } } sock.close (); if (0 != mutex.remove ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("mutex remove"))); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Comparing time ranges...\n"))); // The writer should never overlap any readers bool writer_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { if (writer.any_overlaps (readers[i])) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer overlaps reader %d\n"), i+1)); writer_overlap = true; } } if (!writer_overlap) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer does not overlap with readers; Ok\n"))); // And there should be some overlap between readers. bool reader_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { // Just compare to those higher, else it compares the same ones, // only in reverse. for (int j = i + 1; j < Nr_Processes - 1; ++j) { if (readers[i].any_overlaps (readers[j])) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d overlaps reader %d; Ok\n"), i + 1, j + 1)); reader_overlap = true; } } } if (!reader_overlap) ACE_ERROR ((LM_ERROR, ACE_TEXT ("No readers overlapped!\n"))); ACE_END_TEST; } return 0; }