X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bus%2Fdispatch.c;h=29364665e98975a24f789b7b1f8df73140ff7e1e;hb=78e79022316f45e86a6cac4da85d6b60f5a8f7f8;hp=0b9f9731006ce450027a677cfb05b2e9e01ce520;hpb=1708094c0e00ab433bb0a51981f8b77d24aee256;p=platform%2Fupstream%2Fdbus.git diff --git a/bus/dispatch.c b/bus/dispatch.c index 0b9f973..2936466 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -451,6 +451,30 @@ typedef dbus_bool_t (* Check2Func) (BusContext *context, static dbus_bool_t check_no_leftovers (BusContext *context); +static void +block_connection_until_message_from_bus (BusContext *context, + DBusConnection *connection) +{ + while (dbus_connection_get_dispatch_status (connection) == + DBUS_DISPATCH_COMPLETE && + dbus_connection_get_is_connected (connection)) + { + bus_test_run_bus_loop (context, TRUE); + bus_test_run_clients_loop (FALSE); + } +} + +/* compensate for fact that pop_message() can return #NULL due to OOM */ +static DBusMessage* +pop_message_waiting_for_memory (DBusConnection *connection) +{ + while (dbus_connection_get_dispatch_status (connection) == + DBUS_DISPATCH_NEED_MEMORY) + _dbus_wait_for_memory (); + + return dbus_connection_pop_message (connection); +} + typedef struct { const char *expected_service_name; @@ -470,7 +494,7 @@ check_service_deleted_foreach (DBusConnection *connection, d->failed = TRUE; service_name = NULL; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Did not receive a message on %p, expecting %s\n", @@ -600,7 +624,7 @@ check_no_messages_foreach (DBusConnection *connection, CheckNoMessagesData *d = data; DBusMessage *message; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message != NULL) { _dbus_warn ("Received message %s on %p, expecting no messages\n", @@ -636,7 +660,7 @@ check_service_created_foreach (DBusConnection *connection, d->failed = TRUE; service_name = NULL; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Did not receive a message on %p, expecting %s\n", @@ -746,7 +770,7 @@ check_hello_message (BusContext *context, retval = FALSE; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Did not receive a reply to %s %d on %p\n", @@ -831,7 +855,7 @@ check_hello_message (BusContext *context, /* Client should also have gotten ServiceAcquired */ dbus_message_unref (message); - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Expecting %s, got nothing\n", @@ -971,6 +995,8 @@ check_nonexistent_service_activation (BusContext *context, message = NULL; bus_test_run_everything (context); + block_connection_until_message_from_bus (context, connection); + bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { @@ -980,7 +1006,7 @@ check_nonexistent_service_activation (BusContext *context, retval = FALSE; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Did not receive a reply to %s %d on %p\n", @@ -1035,19 +1061,15 @@ check_nonexistent_service_activation (BusContext *context, } static dbus_bool_t -check_service_activated (BusContext *context, - DBusConnection *connection, - const char *activated_name, - dbus_bool_t require_base_service, - DBusMessage *initial_message, - char **base_service_p) +check_base_service_activated (BusContext *context, + DBusConnection *connection, + DBusMessage *initial_message, + char **base_service_p) { DBusMessage *message; dbus_bool_t retval; DBusError error; char *base_service; - dbus_uint32_t activation_result; - dbus_bool_t already_saw_base_created; base_service = NULL; retval = FALSE; @@ -1055,67 +1077,121 @@ check_service_activated (BusContext *context, dbus_error_init (&error); message = initial_message; - dbus_message_ref (message); - - /* This is kind of a mess since we get the creation of - * the base service only if the activated service didn't - * already exist. Right now the test kills and restarts - * the service each time, so the mess is pointless. - */ - already_saw_base_created = FALSE; + dbus_message_ref (message); - recheck_service_created: if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED)) { char *service_name; CheckServiceCreatedData scd; - + + reget_service_name_arg: if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service_name, DBUS_TYPE_INVALID)) { - _dbus_warn ("Message %s doesn't have a service name: %s\n", - dbus_message_get_name (message), - error.message); - dbus_error_free (&error); - goto out; + if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) + { + dbus_error_free (&error); + _dbus_wait_for_memory (); + goto reget_service_name_arg; + } + else + { + _dbus_warn ("Message %s doesn't have a service name: %s\n", + dbus_message_get_name (message), + error.message); + dbus_error_free (&error); + goto out; + } } - if (!already_saw_base_created && *service_name == ':') + if (*service_name != ':') { - /* This is a base service name, mop up all the - * other messages about it - */ - - base_service = service_name; - service_name = NULL; - - scd.skip_connection = connection; - scd.failed = FALSE; - scd.expected_service_name = base_service; - bus_test_clients_foreach (check_service_created_foreach, - &scd); + _dbus_warn ("Expected base service activation, got \"%s\" instead\n", + service_name); + goto out; + } - if (scd.failed) - goto out; + base_service = service_name; + service_name = NULL; + + scd.skip_connection = connection; + scd.failed = FALSE; + scd.expected_service_name = base_service; + bus_test_clients_foreach (check_service_created_foreach, + &scd); + + if (scd.failed) + goto out; + } + else + { + _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n", + dbus_message_get_name (message)); + goto out; + } - already_saw_base_created = TRUE; + retval = TRUE; - dbus_message_unref (message); - message = dbus_connection_pop_message (connection); - if (message == NULL) + if (base_service_p) + { + *base_service_p = base_service; + base_service = NULL; + } + + out: + if (message) + dbus_message_unref (message); + + if (base_service) + dbus_free (base_service); + + return retval; +} + +static dbus_bool_t +check_service_activated (BusContext *context, + DBusConnection *connection, + const char *activated_name, + const char *base_service_name, + DBusMessage *initial_message) +{ + DBusMessage *message; + dbus_bool_t retval; + DBusError error; + dbus_uint32_t activation_result; + + retval = FALSE; + + dbus_error_init (&error); + + message = initial_message; + dbus_message_ref (message); + + if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED)) + { + char *service_name; + CheckServiceCreatedData scd; + + reget_service_name_arg: + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_INVALID)) + { + if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) + { + dbus_error_free (&error); + _dbus_wait_for_memory (); + goto reget_service_name_arg; + } + else { - _dbus_warn ("Expected a ServiceCreated for the activated service, got nothing\n"); + _dbus_warn ("Message %s doesn't have a service name: %s\n", + dbus_message_get_name (message), + error.message); + dbus_error_free (&error); goto out; } - - goto recheck_service_created; - } - else if (require_base_service && !already_saw_base_created) - { - _dbus_warn ("Did not get a ServiceCreated for a base service, it was for %s instead\n", - service_name); - goto out; } if (strcmp (service_name, activated_name) != 0) @@ -1138,7 +1214,7 @@ check_service_activated (BusContext *context, goto out; dbus_message_unref (message); - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { _dbus_warn ("Expected a reply to %s, got nothing\n", @@ -1146,7 +1222,13 @@ check_service_activated (BusContext *context, goto out; } } - + else + { + _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n", + activated_name, dbus_message_get_name (message)); + goto out; + } + if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE)) { _dbus_warn ("Expected reply to %s, got message %s instead\n", @@ -1194,19 +1276,10 @@ check_service_activated (BusContext *context, } retval = TRUE; - - if (base_service_p) - { - *base_service_p = base_service; - base_service = NULL; - } out: if (message) dbus_message_unref (message); - - if (base_service) - dbus_free (base_service); return retval; } @@ -1262,6 +1335,154 @@ check_service_deactivated (BusContext *context, return retval; } +static dbus_bool_t +check_send_exit_to_service (BusContext *context, + DBusConnection *connection, + const char *service_name, + const char *base_service) +{ + dbus_bool_t got_error; + DBusMessage *message; + dbus_int32_t serial; + dbus_bool_t retval; + + _dbus_verbose ("Sending exit message to the test service\n"); + + retval = FALSE; + + /* Kill off the test service by sending it a quit message */ + message = dbus_message_new (service_name, + "org.freedesktop.DBus.TestSuiteExit"); + + if (message == NULL) + { + /* Do this again; we still need the service to exit... */ + if (!check_send_exit_to_service (context, connection, + service_name, base_service)) + goto out; + + return TRUE; + } + + if (!dbus_connection_send (connection, message, &serial)) + { + dbus_message_unref (message); + + /* Do this again; we still need the service to exit... */ + if (!check_send_exit_to_service (context, connection, + service_name, base_service)) + goto out; + + return TRUE; + } + + dbus_message_unref (message); + message = NULL; + + /* send message */ + bus_test_run_clients_loop (TRUE); + + /* read it in and write it out to test service */ + bus_test_run_bus_loop (context, FALSE); + + /* see if we got an error during message bus dispatching */ + bus_test_run_clients_loop (FALSE); + message = dbus_connection_borrow_message (connection); + got_error = message != NULL && dbus_message_get_is_error (message); + if (message) + dbus_connection_return_message (connection, message); + + if (!got_error) + { + /* If no error, wait for the test service to exit */ + block_connection_until_message_from_bus (context, connection); + + bus_test_run_everything (context); + } + + if (got_error) + { + message = pop_message_waiting_for_memory (connection); + _dbus_assert (message != NULL); + + if (!dbus_message_get_is_error (message)) + { + _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n", + dbus_message_get_name (message)); + goto out; + } + else if (!dbus_message_name_is (message, DBUS_ERROR_NO_MEMORY)) + { + _dbus_warn ("not expecting error %s when asking test service to exit\n", + dbus_message_get_name (message)); + goto out; + } + + _dbus_verbose ("Got error %s when asking test service to exit\n", + dbus_message_get_name (message)); + + /* Do this again; we still need the service to exit... */ + if (!check_send_exit_to_service (context, connection, + service_name, base_service)) + goto out; + } + else + { + if (!check_service_deactivated (context, connection, + service_name, base_service)) + goto out; + } + + retval = TRUE; + + out: + if (message) + dbus_message_unref (message); + + return retval; +} + +static dbus_bool_t +check_got_error (BusContext *context, + DBusConnection *connection, + const char *error_name) +{ + DBusMessage *message; + dbus_bool_t retval; + + retval = FALSE; + + message = pop_message_waiting_for_memory (connection); + if (message == NULL) + { + _dbus_warn ("Did not get an expected error\n"); + goto out; + } + + if (!dbus_message_get_is_error (message)) + { + _dbus_warn ("Expected an error, got %s\n", + dbus_message_get_name (message)); + goto out; + } + + if (!dbus_message_name_is (message, error_name)) + { + _dbus_warn ("Expected error %s, got %s instead\n", + error_name, + dbus_message_get_name (message)); + goto out; + } + + retval = TRUE; + + out: + if (message) + dbus_message_unref (message); + + return retval; +} + #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService" /* returns TRUE if the correct thing happens, @@ -1307,12 +1528,11 @@ check_existent_service_activation (BusContext *context, bus_test_run_everything (context); - if (dbus_connection_get_dispatch_status (connection) == - DBUS_DISPATCH_COMPLETE) - /* now wait for the message bus to hear back from the activated service */ - bus_test_run_bus_loop (context, TRUE); - - /* and process everything again */ + /* now wait for the message bus to hear back from the activated + * service. + */ + block_connection_until_message_from_bus (context, connection); + bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) @@ -1323,16 +1543,17 @@ check_existent_service_activation (BusContext *context, retval = FALSE; - message = dbus_connection_pop_message (connection); + message = pop_message_waiting_for_memory (connection); if (message == NULL) { - _dbus_warn ("Did not receive a reply to %s %d on %p\n", + _dbus_warn ("Did not receive any messages after %s %d on %p\n", DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection); goto out; } - _dbus_verbose ("Received %s on %p\n", - dbus_message_get_name (message), connection); + _dbus_verbose ("Received %s on %p after sending %s\n", + dbus_message_get_name (message), connection, + DBUS_MESSAGE_ACTIVATE_SERVICE); if (dbus_message_get_is_error (message)) { @@ -1350,16 +1571,9 @@ check_existent_service_activation (BusContext *context, ; /* good, this is a valid response */ } else if (dbus_message_name_is (message, - DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND)) - { - ; /* good, this is expected also */ - } - else if (dbus_message_name_is (message, DBUS_ERROR_SPAWN_CHILD_EXITED)) { - ; /* good, this is expected also (child will exit if for example we don't - * have memory to register it) - */ + ; /* good, this is expected also */ } else { @@ -1370,51 +1584,208 @@ check_existent_service_activation (BusContext *context, } else { - if (!check_service_activated (context, connection, - EXISTENT_SERVICE_NAME, TRUE, - message, &base_service)) + dbus_bool_t got_service_deleted; + dbus_bool_t got_error; + + if (!check_base_service_activated (context, connection, + message, &base_service)) goto out; dbus_message_unref (message); message = NULL; - - /* Now kill off the test service by sending it a quit message */ - message = dbus_message_new (EXISTENT_SERVICE_NAME, - "org.freedesktop.DBus.TestSuiteExit"); + + /* We may need to block here for the test service to exit or finish up */ + block_connection_until_message_from_bus (context, connection); + message = dbus_connection_borrow_message (connection); if (message == NULL) { - dbus_free (base_service); - return TRUE; + _dbus_warn ("Did not receive any messages after base service creation notification\n"); + goto out; } + + got_service_deleted = dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED); + got_error = dbus_message_get_is_error (message); - if (!dbus_connection_send (connection, message, &serial)) + dbus_connection_return_message (connection, message); + message = NULL; + + if (got_error) { + if (!check_got_error (context, connection, + DBUS_ERROR_SPAWN_CHILD_EXITED)) + goto out; + + /* A service deleted should be coming along now after this error. + * We can also get the error *after* the service deleted. + */ + got_service_deleted = TRUE; + } + + if (got_service_deleted) + { + /* The service started up and got a base address, but then + * failed to register under EXISTENT_SERVICE_NAME + */ + CheckServiceDeletedData csdd; + + csdd.expected_service_name = base_service; + csdd.failed = FALSE; + bus_test_clients_foreach (check_service_deleted_foreach, + &csdd); + + if (csdd.failed) + goto out; + + /* Now we should get an error about the service exiting + * if we didn't get it before. + */ + if (!got_error) + { + block_connection_until_message_from_bus (context, connection); + + /* and process everything again */ + bus_test_run_everything (context); + + if (!check_got_error (context, connection, + DBUS_ERROR_SPAWN_CHILD_EXITED)) + goto out; + } + } + else + { + message = pop_message_waiting_for_memory (connection); + if (message == NULL) + { + _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n"); + goto out; + } + + if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME, + base_service, message)) + goto out; + dbus_message_unref (message); - dbus_free (base_service); - return TRUE; + message = NULL; + + + if (!check_no_leftovers (context)) + { + _dbus_warn ("Messages were left over after successful activation\n"); + goto out; + } + + if (!check_send_exit_to_service (context, connection, + EXISTENT_SERVICE_NAME, base_service)) + goto out; } + } + + retval = TRUE; + + out: + if (message) + dbus_message_unref (message); + + if (base_service) + dbus_free (base_service); + + return retval; +} + +/* returns TRUE if the correct thing happens, + * but the correct thing may include OOM errors. + */ +static dbus_bool_t +check_segfault_service_activation (BusContext *context, + DBusConnection *connection) +{ + DBusMessage *message; + dbus_int32_t serial; + dbus_bool_t retval; + DBusError error; + + dbus_error_init (&error); + + message = dbus_message_new (DBUS_SERVICE_DBUS, + DBUS_MESSAGE_ACTIVATE_SERVICE); + if (message == NULL) + return TRUE; + + if (!dbus_message_append_args (message, + DBUS_TYPE_STRING, + "org.freedesktop.DBus.TestSuiteSegfaultService", + DBUS_TYPE_UINT32, 0, + DBUS_TYPE_INVALID)) + { dbus_message_unref (message); - message = NULL; + return TRUE; + } + + if (!dbus_connection_send (connection, message, &serial)) + { + dbus_message_unref (message); + return TRUE; + } + + dbus_message_unref (message); + message = NULL; - /* send message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_everything (context); + block_connection_until_message_from_bus (context, connection); + bus_test_run_everything (context); - /* read it in and write it out to test service */ - bus_test_run_bus_loop (context, FALSE); - - if (dbus_connection_get_dispatch_status (connection) == - DBUS_DISPATCH_COMPLETE) - /* now wait for the message bus to hear back from the activated service exiting */ - bus_test_run_bus_loop (context, TRUE); - - /* and process everything again */ - bus_test_run_everything (context); + if (!dbus_connection_get_is_connected (connection)) + { + _dbus_verbose ("connection was disconnected\n"); + return TRUE; + } + + retval = FALSE; + + message = pop_message_waiting_for_memory (connection); + if (message == NULL) + { + _dbus_warn ("Did not receive a reply to %s %d on %p\n", + DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection); + goto out; + } + + _dbus_verbose ("Received %s on %p\n", + dbus_message_get_name (message), connection); + + if (dbus_message_get_is_error (message)) + { + if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS)) + { + _dbus_warn ("Message has wrong sender %s\n", + dbus_message_get_sender (message) ? + dbus_message_get_sender (message) : "(none)"); + goto out; + } - if (!check_service_deactivated (context, connection, - EXISTENT_SERVICE_NAME, base_service)) - goto out; + if (dbus_message_name_is (message, + DBUS_ERROR_NO_MEMORY)) + { + ; /* good, this is a valid response */ + } + else if (dbus_message_name_is (message, + DBUS_ERROR_SPAWN_CHILD_SIGNALED)) + { + ; /* good, this is expected also */ + } + else + { + _dbus_warn ("Did not expect error %s\n", + dbus_message_get_name (message)); + goto out; + } + } + else + { + _dbus_warn ("Did not expect to successfully activate segfault service\n"); + goto out; } retval = TRUE; @@ -1422,9 +1793,6 @@ check_existent_service_activation (BusContext *context, out: if (message) dbus_message_unref (message); - - if (base_service) - dbus_free (base_service); return retval; } @@ -1554,16 +1922,17 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!check_hello_message (context, baz)) _dbus_assert_not_reached ("hello message failed"); -#if 0 - check2_try_iterations (context, foo, "existent_service_activation", - check_existent_service_activation); -#endif + check1_try_iterations (context, "create_and_hello", + check_hello_connection); check2_try_iterations (context, foo, "nonexistent_service_activation", check_nonexistent_service_activation); - check1_try_iterations (context, "create_and_hello", - check_hello_connection); + check2_try_iterations (context, foo, "segfault_service_activation", + check_segfault_service_activation); + + check2_try_iterations (context, foo, "existent_service_activation", + check_existent_service_activation); _dbus_verbose ("Disconnecting foo, bar, and baz\n");