Its purpose is to contact the 'boot-properties' service during the
boot process and to set the list of system properties read from the
emulator program through it.
It must be launched from /system/etc/init.goldfish.rc as root.
It depends on the 'boot-properties' service being implemented by the
emulator (in a later patch). If not available, it will simply timeout.
This also fixes a potential crash in qemud which can happen in the following case:
- client sends a command to a service
- the service responds with one or more message
- the service immediately closes the connection before the client can read the data
what happened is that the FDHandler object was buffering out-going packets to the
client, but the Multiplexer acted on the disconnection immediately. This resulted
in:
- client_free() being called
- fdhandler_shutdown() being called
- the FDHandler being placed on the 'closing' list to be able to send
buffered packets later. And 'receiver_close' being called
- client_fd_close() being called, which would call client_free()
recursively
- the second client_free() call would free the object
- the first client_free() call would try to free the object again
- ==> dlmalloc() detects a double-free and immediately aborts.
the fixes simply avoids the calle to receiver_close() in fdhandler_shutdown()
since this function is called from an explicit shutdown request from the multiplexer,
it doesn't correspond to the case where the client has closed the connection itself.
115 lines
3.0 KiB
C
115 lines
3.0 KiB
C
/*
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/* this program is used to read a set of system properties and their values
|
|
* from the emulator program and set them in the currently-running emulated
|
|
* system. It does so by connecting to the 'boot-properties' qemud service.
|
|
*
|
|
* This program should be run as root and called from
|
|
* /system/etc/init.goldfish.rc exclusively.
|
|
*/
|
|
|
|
#define LOG_TAG "qemu-props"
|
|
|
|
#define DEBUG 1
|
|
|
|
#if DEBUG
|
|
# include <cutils/log.h>
|
|
# define DD(...) LOGI(__VA_ARGS__)
|
|
#else
|
|
# define DD(...) ((void)0)
|
|
#endif
|
|
|
|
#include <cutils/properties.h>
|
|
#include <unistd.h>
|
|
#include <hardware/qemud.h>
|
|
|
|
/* Name of the qemud service we want to connect to.
|
|
*/
|
|
#define QEMUD_SERVICE "boot-properties"
|
|
|
|
#define MAX_TRIES 5
|
|
|
|
int main(void)
|
|
{
|
|
int qemud_fd, count = 0;
|
|
|
|
/* try to connect to the qemud service */
|
|
{
|
|
int tries = MAX_TRIES;
|
|
|
|
while (1) {
|
|
qemud_fd = qemud_channel_open( "boot-properties" );
|
|
if (qemud_fd >= 0)
|
|
break;
|
|
|
|
if (--tries <= 0) {
|
|
DD("Could not connect after too many tries. Aborting");
|
|
return 1;
|
|
}
|
|
|
|
DD("waiting 1s to wait for qemud.");
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
DD("connected to '%s' qemud service.", QEMUD_SERVICE);
|
|
|
|
/* send the 'list' command to the service */
|
|
if (qemud_channel_send(qemud_fd, "list", -1) < 0) {
|
|
DD("could not send command to '%s' service", QEMUD_SERVICE);
|
|
return 1;
|
|
}
|
|
|
|
/* read each system property as a single line from the service,
|
|
* until exhaustion.
|
|
*/
|
|
for (;;)
|
|
{
|
|
#define BUFF_SIZE (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2)
|
|
|
|
char* q;
|
|
char temp[BUFF_SIZE];
|
|
int len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1);
|
|
|
|
if (len < 0 || len > BUFF_SIZE-1)
|
|
break;
|
|
|
|
temp[len] = '\0'; /* zero-terminate string */
|
|
|
|
DD("received: %.*s", len, temp);
|
|
|
|
/* separate propery name from value */
|
|
q = strchr(temp, '=');
|
|
if (q == NULL) {
|
|
DD("invalid format, ignored.");
|
|
continue;
|
|
}
|
|
*q++ = '\0';
|
|
|
|
if (property_set(temp, q) < 0) {
|
|
DD("could not set property '%s' to '%s'", temp, q);
|
|
} else {
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
/* finally, close the channel and exit */
|
|
close(qemud_fd);
|
|
DD("exiting (%d properties set).", count);
|
|
return 0;
|
|
}
|