Not able to Push Log Data using KAA 0.10 C SDK - kaa

We have created one local cloud instance using KAA 0.10 and generated C Posix SDK after adding some Log Upload Schema.
I have created one sample program in which just create one KAA client and update dummy endpoints and started KAA client in which one dummy callback function will be called which is working fine without any issue.
After that, I have extended my working code to upload Log Data on some events like every 1 seconds or every 5 logs count and executed same code on my Linux System but I am getting "failed_log_delivery_callback" randomly not as per strategy defined.
Please find following code which I am using to check Log Upload Strategy using KAA 0.10 C SDK.
/* Set of routines that handles log delivery events */
static void success_log_delivery_callback(void *context, const kaa_log_bucket_info_t *bucket)
{
printf("+++++++++++++++++ success_log_delivery_callback called +++++++++++++++++++++++\n");
printf("Bucket: %u is successfully delivered. Logs uploaded: %zu\n",
bucket->bucket_id,
bucket->log_count);
}
static void failed_log_delivery_callback(void *context, const kaa_log_bucket_info_t *bucket)
{
printf("+++++++++++++++++ failed_log_delivery_callback called +++++++++++++++++++++++\n");
printf("Log delivery of the bucket: %u is failed!\n", bucket->bucket_id);
}
static void timeout_log_delivery_callback(void *context, const kaa_log_bucket_info_t *bucket)
{
printf("+++++++++++++++++ timeout_log_delivery_callback called +++++++++++++++++++++++\n");
printf("Timeout reached for log delivery of the bucket: %u!\n", bucket->bucket_id);
}
/* Log delivery listener callbacks. Each callback called whenever something happen with a log bucket. */
kaa_log_delivery_listener_t log_listener = {
.on_success = success_log_delivery_callback, /* Called if log delivered successfully */
.on_failed = failed_log_delivery_callback, /* Called if delivery failed */
.on_timeout = timeout_log_delivery_callback, /* Called if timeout occurs */
.ctx = NULL, /* Optional context */
};
kaa_union_t *kaa_logging_union_create(const char *data, uint8_t type, destroy_fn destroy)
{
kaa_union_t *str;
str = kaa_logging_union_string_or_null_branch_0_create();
str->data = kaa_string_move_create(data,NULL);
return str;
}
kaa_union_t *kaa_profile_union_create(const char *data, uint8_t type, destroy_fn destroy)
{
kaa_union_t *str;
str = kaa_logging_union_string_or_null_branch_0_create();
str->data = kaa_string_move_create(data,NULL);
return str;
}
static void dummy_function(void *context)
{
kaa_error_t error_code = 0;
printf("\n\n**************** Hello, I am a Kaa Application!!!!!!!!!!!!!!!!!!!!!!\n\n");
kaa_logging_event_push_t *log_push;
/* Log information. Populated when log is added via kaa_logging_add_record() */
kaa_log_record_info_t log_info;
/* kaa logging event push data will be created from here */
log_push = kaa_logging_event_push_create();
if(log_push == NULL)
{
printf("can not create log data\r\n");
kaa_client_stop(kaa_client);
return;
}
log_push->tag = kaa_logging_union_create("67891",0,NULL);
if(log_push->tag == NULL)
{
printf("can not create log data\r\n");
kaa_client_stop(kaa_client);
return;
}
log_push->rid = kaa_logging_union_create("77:88:99:11:22:33",0,NULL);
if(log_push->rid == NULL)
{
printf("can not create log data\r\n");
kaa_client_stop(kaa_client);
return;
}
log_push->var = kaa_logging_union_create("HIJKLMN",0,NULL);
if(log_push->var == NULL)
{
printf("can not create log data\r\n");
kaa_client_stop(kaa_client);
return;
}
log_push->payload = kaa_string_move_create("Linux System KAA Message",NULL);
if(log_push->payload == NULL)
{
printf("can not create log data\r\n");
kaa_client_stop(kaa_client);
return;
}
/* kaa logging push data will be added from here */
error_code = kaa_logging_add_record(kaa_client_get_context(kaa_client)->log_collector, log_push, &log_info);
if (error_code)
{
printf("Failed to add log record, error code %d\n", error_code);
kaa_client_stop(kaa_client);
return;
}
printf("log message added :: count :: %d\r\n", kaa_log_count);
/* kaa logging push data will be destroyed from here */
log_push->destroy(log_push);
kaa_log_count++;
/* kaa client will be stopped from here */
/*error_code = kaa_client_stop(kaa_client);
if (error_code)
{
printf("kaa_client_stop is failed to execute.....\n");
return;
}
else
printf("kaa_client_stop is executed successfully.....\n"); */
}
int main(void)
{
kaa_error_t error_code = 0;
int i = 0;
void *log_storage_context = NULL, *log_upload_strategy_context = NULL;
printf("*********** kaa_basic_main started **************\n");
kaa_profile_t *profile = NULL;
printf("Before kaa_client_create API...\n");
/* kaa client will be created from here */
error_code = kaa_client_create(&kaa_client, NULL);
if (error_code)
{
printf("kaa_client_create API is failed to execute...\n");
return EXIT_FAILURE;
}
else
printf("kaa_client_create API is called successfully...\n");
sleep(2);
kaa_endpoint_id_p buff = (kaa_endpoint_id_p)malloc(23);
/* kaa profile manager endpoint id comes from here */
error_code = kaa_profile_manager_get_endpoint_id(kaa_client_get_context(kaa_client)->profile_manager,buff);
if (error_code)
{
printf("kaa_profile_manager_get_endpoint_id is failed to execute.....\n");
return EXIT_FAILURE;
}
else
{
for(i = 0; i < 23; i++)
{
printf("kaa_profile_manager_get_endpoint_id[i] :: 0x%x\n", buff[i]);
}
printf("kaa_profile_manager_get_endpoint_id API is called successfully...\n");
}
free(buff);
/* kaa profile will be created from here */
profile = (kaa_profile_t *)kaa_profile_profile_create();
printf("kaa_profile_profile_create API is called...\n");
profile->id = kaa_string_move_create(id,NULL);
profile->key = kaa_string_move_create((const char *)key,NULL);
profile->current_firmware_version = kaa_string_move_create(f_version,NULL);
profile->serial_number = kaa_string_move_create(ser_number,NULL);
profile->health = kaa_string_move_create(health,NULL);
profile->pii = kaa_string_move_create(pii,NULL);
profile->info = kaa_string_move_create(info,NULL);
sleep(2);
printf("before kaa_profile_manager_update_profile API is called...\n");
/* kaa profile will be updated from here */
error_code = kaa_profile_manager_update_profile(kaa_client_get_context(kaa_client)->profile_manager, profile);
if (error_code)
{
printf("kaa_profile_manager_update_profile is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("kaa_profile_manager_update_profile API is called successfully...\n");
sleep(2);
printf("before calling kaa_client_start.....\n");
/* The internal memory log storage distributed with Kaa SDK */
error_code = ext_unlimited_log_storage_create(&log_storage_context, kaa_client_get_context(kaa_client)->logger);
if (error_code)
{
printf("ext_unlimited_log_storage_create is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("ext_unlimited_log_storage_create is executed successfully.....\n");
/* KAA Upload Strategy will be created with timeout */
error_code = ext_log_upload_strategy_create(kaa_client_get_context(kaa_client), &log_upload_strategy_context, KAA_LOG_UPLOAD_BY_TIMEOUT_STRATEGY);
if (error_code)
{
printf("ext_log_upload_strategy_create is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("ext_log_upload_strategy_create is executed successfully.....\n");
/* Strategy will upload logs every 1 seconds. */
error_code = ext_log_upload_strategy_set_upload_timeout(log_upload_strategy_context, 1);
if (error_code)
{
printf("ext_log_upload_strategy_set_threshold_count is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("ext_log_upload_strategy_set_threshold_count is executed successfully.....\n");
/* Specify log bucket size constraints */
kaa_log_bucket_constraints_t bucket_sizes = {
.max_bucket_size = 512, /* Bucket size in bytes */
.max_bucket_log_count = 5, /* Maximum log count in one bucket */
};
/* Initialize the log storage and strategy (by default it is not set) */
error_code = kaa_logging_init(kaa_client_get_context(kaa_client)->log_collector
, log_storage_context
, log_upload_strategy_context
, &bucket_sizes);
if (error_code)
{
printf("kaa_logging_init is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("kaa_logging_init is executed successfully.....\n");
/* Add listeners to a log collector */
kaa_logging_set_listeners(kaa_client_get_context(kaa_client)->log_collector, &log_listener);
if (error_code)
{
printf("kaa_logging_set_listeners is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("kaa_logging_set_listeners is executed successfully.....\n");
/* kaa client will be started from here */
error_code = kaa_client_start(kaa_client, dummy_function, (void *)kaa_client, 0);
if (error_code)
{
printf("kaa_client_start is failed to execute.....\n");
return EXIT_FAILURE;
}
else
printf("kaa_client_start is executed successfully.....\n");
printf("after calling kaa_client_start.....\n");
sleep(2);
/* kaa client will be destroyed from here */
kaa_client_destroy(kaa_client);
printf("after calling kaa_client_destroy.....\n");
return EXIT_SUCCESS;
}
Let me know if need any more details from my-side.

Related

how to handle stale event in nginx

These days, I am studying the nginx source code.
But there is a question about stale event.
If there is some coming event : #1, #2,#3 .. #40,
When we deal with #1, #40 will shut down and it's variables instance is 0
and #2.#3 is a new connection,
Accept function to allocate a new descriptor which is just free (#40),
when we deal with #2,
we need to invoke function named ngx_event_accept, and then invoke ngx_get_connection,
but unfortunately after that ,we failed which mean we need to free connection,but we have invoked ngx_get_connection once which means variables instance have changed once.
just like the following code (success and failed )
void ngx_event_accept(ngx_event_t *ev)
{
...
/* success */
c = ngx_get_connection(s, ev->log);
if (c == NULL) {
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
return;
}
c->type = SOCK_STREAM;
...
/* failed */
c->pool = ngx_create_pool(ls->pool_size, ev->log);
if (c->pool == NULL) {
ngx_close_accepted_connection(c);
return;
}
c->sockaddr = ngx_palloc(c->pool, socklen);
if (c->sockaddr == NULL) {
ngx_close_accepted_connection(c);
return;
}
ngx_memcpy(c->sockaddr, sa, socklen);
/* or failed here */
log = ngx_palloc(c->pool, sizeof(ngx_log_t));
if (log == NULL) {
ngx_close_accepted_connection(c);
return;
}
....
}
when we deal with #3,we success, the fd set to 40, and the value of instance is changed again.
Now it's the same with before, so the following Judgment statement in the function named ngx_epoll_process_events will not work,
if (c->fd == -1 || rev->instance != instance) {
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: stale event %p", c);
continue;
}
I know it can post event which put in in queue not handle,but if i don't use ngx_use_accept_mutex,which means the flag in function ngx_process_events_and_timers doesn't include NGX_POST_EVENTS,
in this case,it will not post event but handle event immediately and it's wrong because #40 is stale event.

Android BLE: writing >20 bytes characteristics missing the last byte array

I have been implementing the module to send the bytes in chunks, 20 bytes each onto the MCU device via BLE. When it comes to writing the bytes more than 60 bytes and so on, the last chunk of the bytes ( usually less than 20 bytes) is often missed. Hence, the MCU device cannot get the checksum and write the value. I have modified the call back to Thread.sleep(200) to change it but it sometimes works on writing 61 bytes or sometimes not. Would you please tell me are there any synchronous method to write the bytes in chunks ? The below is my working :
#Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
try {
Thread.sleep(300);
if (status != BluetoothGatt.GATT_SUCCESS) {
disconnect();
return;
}
if(status == BluetoothGatt.GATT_SUCCESS) {
System.out.println("ok");
broadcastUpdate(ACTION_DATA_READ, mReadCharacteristic, status);
}
else {
System.out.println("fail");
broadcastUpdate(ACTION_DATA_WRITE, characteristic, status);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized boolean writeCharacteristicData(BluetoothGattCharacteristic characteristic ,
byte [] byteResult ) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return false;
}
boolean status = false;
characteristic.setValue(byteResult);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
status = mBluetoothGatt.writeCharacteristic(characteristic);
return status;
}
private void sendCommandData(final byte [] commandByte) {
// TODO Auto-generated method stub
if(commandByte.length > 20 ){
final List<byte[]> bytestobeSent = splitInChunks(commandByte);
for(int i = 0 ; i < bytestobeSent.size() ; i ++){
for(int k = 0 ; k < bytestobeSent.get(i).length ; k++){
System.out.println("LumChar bytes : "+ bytestobeSent.get(i)[k] );
}
BluetoothGattService LumService = mBluetoothGatt.getService(A_SERVICE);
if (LumService == null) { return; }
BluetoothGattCharacteristic LumChar = LumService.getCharacteristic(AW_CHARACTERISTIC);
if (LumChar == null) { System.out.println("LumChar"); return; }
//Thread.sleep(500);
writeCharacteristicData(LumChar , bytestobeSent.get(i));
}
}else{
....
You need to wait for the onCharacteristicWrite() callback to be invoked before sending the next write. The typical solution is to make a job queue and pop a job off the queue for each callback you get to onCharacteristicWrite(), onCharacteristicRead(), etc.
In other words, you can't do it in a for loop unfortunately, unless you want to set up some kind of lock that waits for the callback before going on to the next iteration. In my experience a job queue is a cleaner general-purpose solution though.

LwIP Netconn API + FreeRTOS TCP Client Buffer Issue

I've been trying to modify the tcp server example with LwIP in STM32F4DISCOVERY board. I have to write a sender which does not necessarily have to reply server responses. It can send data with 100 ms frequency, for example.
Firstly, the example of TCP server is like this:
static void tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL) {
/* Bind connection to well known port number 7. */
err = netconn_bind(conn, NULL, DEST_PORT);
if (err == ERR_OK) {
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/* Process the new connection. */
if (newconn) {
struct netbuf *buf;
void *data;
u16_t len;
while ((buf = netconn_recv(newconn)) != NULL) {
do {
netbuf_data(buf, &data, &len);
//Incoming package
.....
//Check for data
if (DATA IS CORRECT)
{
//Reply
data = "OK";
len = 2;
netconn_write(newconn, data, len, NETCONN_COPY);
}
} while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
}
}
} else {
printf(" can not bind TCP netconn");
}
} else {
printf("can not create TCP netconn");
}
}
I modified this code to obtain a client version, this is what I've got so far:
static void tcpecho_thread(void *arg)
{
struct netconn *xNetConn = NULL;
struct ip_addr local_ip;
struct ip_addr remote_ip;
int rc1, rc2;
struct netbuf *Gonderilen_Buf = NULL;
struct netbuf *gonderilen_buf = NULL;
void *b_data;
u16_t b_len;
IP4_ADDR( &local_ip, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3 );
IP4_ADDR( &remote_ip, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
xNetConn = netconn_new ( NETCONN_TCP );
rc1 = netconn_bind ( xNetConn, &local_ip, DEST_PORT );
rc2 = netconn_connect ( xNetConn, &remote_ip, DEST_PORT );
b_data = "+24C"; // Data to be send
b_len = sizeof ( b_data );
while(1)
{
if ( rc1 == ERR_OK )
{
// If button pressed, send data "+24C" to server
if (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET)
{
Buf = netbuf_new();
netbuf_alloc(Buf, 4); // 4 bytes of buffer
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
vTaskDelay(100); // To see the result easily in Comm Operator
netbuf_delete(Buf);
}
}
if ( rc1 != ERR_OK || rc2 != ERR_OK )
{
netconn_delete ( xNetConn );
}
}
}
While the writing operation works, netconn_write sends what's on its buffer. It doesnt care whether b_data is NULL or not. I've tested it by adding the line b_data = NULL;
So the resulting output in Comm Operator is like this:
Rec:(02:47:27)+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C
However, I want it to work like this:
Rec:(02:47:22)+24C
Rec:(02:47:27)+24C
Rec:(02:57:12)+24C
Rec:(02:58:41)+24C
The desired write operation happens when I wait for around 8 seconds before I push the button again.
Since netconn_write function does not allow writing to a buffer, I'm not able to clear it. And netconn_send is only allowed for UDP connections.
I need some guidance to understand the problem and to generate a solution for it.
Any help will be greately appreciated.
It's just a matter of printing the result in the correct way.
You can try to add this part of code before writing in the netbuf data structure:
char buffer[20];
sprintf(buffer,"24+ \n");
Buf->p->payload = "+24C";
I see one or two problems in your code, depending on what you want it exactly to do. First of all, you're not sending b_data at all, but a constant string:
b_data = "+24C"; // Data to be send
and then
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
b_data is not anywhere mentioned there. What is sent is the payload. Try Buf->p->payload = b_data; if it's what you want to achieve.
Second, if you want the +24C text to be sent only once when you push the button, you'll have to have a loop to wait for the button to open again before continuing the loop, or it will send +24C continuously until you stop pushing the button. Something in this direction:
while (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET) {
vTaskDelay(1);
}

ptrace(PTRACE_CONT) cannot resume just-attached processes

I am writing a program that needs to attach to other processes (which might be created by a previous instance of my program) and watch when they terminate.
If I keep my program running during the lifetime of the processes I created, everything works fine; but if I start a process, kill my program, then restart it, the previously created process would remains in STOPPED state forever (it seems that the ptrace(PTRACE_CONT,...) can not resume it). The code snippet is attached bellow:
static int exitFlag = 0;
static void sighandler (int/* signum */)
{ exitFlag = 1; }
int JsfNode::run (void)
{
/* load jobs */
{
vector <JobInfo2> jobs;
loadStruct <vector <JobInfo2> > (
jobFile (), jobs);
for (unsigned i=0 ; i<jobs.size () ; i++) {
JobInfo2& info = jobs [i];
string name = info.parm.name;
if (m_jobs.find (name) == m_jobs.end ()) {
Job2& job = m_jobs [name];
job.info = info;
/* trace it so that we can wait() it */
switch (info.state) {
case js2Active:
case js2Canceling:
case js2Suspending:
if (ptrace (PTRACE_ATTACH, info.pid, 0, 0))
jdebug ("PTRACE_ATTACH failed for: %d (%s)\n", info.pid,
strerror (errno));
default: break;
}
}
}
}
/* run until we are signaled to stop */
signal (SIGINT, sighandler);
while (!exitFlag)
sleep (1);
/* save jobs */
{
vector <JobInfo2> jobs;
for (map <string, Job2>::iterator it=m_jobs.begin () ;
it!=m_jobs.end () ; it++) {
JobInfo2& info = it->second.info;
ptrace (PTRACE_DETACH, info.pid, NULL, NULL);
jobs.push_back (info);
}
saveStruct <vector <JobInfo2> > (
jobFile (), jobs);
}
return 0;
}
void JsfNode::startJob (Job2 & job)
{
JobParm2 parm = job.info.parm;
jdebug ("starting \"%s\"..\n", parm.name.c_str());
/* get the uid of the run-as user */
uid_t uid = 0; /* run as root if the specified user is invalid */
struct passwd * pwe = getpwnam (parm.user.c_str());
if (pwe != NULL)
uid = pwe->pw_uid;
/* prepare the script file */
string scriptfile = m_workdir+"/"+parm.name+"_scriptfile";
ofstream ofscriptfile (scriptfile.c_str());
ofscriptfile << parm.script;
ofscriptfile.close();
chown (scriptfile.c_str(), uid, uid);
chmod (scriptfile.c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
/* prepare the MPIMACHINEFILE */
string machinefile = m_workdir+"/"+parm.name+"_machinefile";
ofstream ofmachinefile (machinefile.c_str());
for (Resource::iterator it=parm.res.begin () ; it!=parm.res.end () ; it++)
ofmachinefile << *it << ':' << parm.taskPerNode << '\n';
ofmachinefile.close ();
chown (machinefile.c_str(), uid, uid);
chmod (machinefile.c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
/* prepare the redirection channels */
int ipipe [2] = {-1,-1};
int opipe [2] = {-1,-1};
if (parm.redio > 0) {
if (pipe (ipipe) == -1) {
unlink:
unlink (machinefile.c_str());
unlink (scriptfile.c_str());
return; /* do not fail the job, just try later */
}
if (pipe (opipe) == -1) {
close:
close (ipipe [0]);
close (ipipe [1]);
goto unlink;
}
}
/* OK, fork it! -----------------> */
pid_t pid;
if ((pid = fork ()) == -1) {
close (opipe [0]);
close (opipe [1]);
goto close;
}
if (pid == 0) {
/* enable parent-tracing */
ptrace (PTRACE_TRACEME, 0, NULL, NULL);
/* drop the root privilege */
setuid (uid);
/* redirect stdin/stdout */
if (parm.redio) {
if (dup2 (ipipe [0],0)<0 ||
dup2 (opipe [1],1)<0)
exit (errno);
close (ipipe [0]);
close (ipipe [1]);
close (opipe [0]);
close (opipe [1]);
}
/* prepare the arguments/environments */
char * arg[] = {
strdup (scriptfile.c_str()),
strdup (parm.args.c_str()),
NULL /* the required null entry */
};
setenv ("MPIMACHINEFILE", machinefile.c_str(), 1);
setenv ("DISPLAY", parm.headNode.c_str(), 1);
setenv ("JSF_JOBID", parm.name.c_str(), 1);
/* execute it! ------> */
execv (scriptfile.c_str(), arg);
exit (errno);
}
/* redirect stdin/stdout */
if (parm.redio) {
close (ipipe [0]);
close (opipe [1]);
job.redPipe [0] = opipe [0];
job.redPipe [1] = ipipe [1];
}
/* start the nurse thread */
NurseData * nd = new NurseData (this, job);
if (pthread_create (&job.nurseId, NULL, ::_jobnurse, nd) == 0)
job.nurseActive = true;
else delete nd;
job.info.pid = pid;
setJobState (job, js2Active);
return;
}
void JsfNode::monitorJob (Job2 & job)
{
int status;
pid_t pid = waitpid (job.info.pid, &status, WNOHANG);
if (pid < 0) {
if (errno == ECHILD) {
/* the job process has disappeared.. */
job.exitCode = 0;
setJobState (job, js2Finished);
return;
}
} else if (pid == job.info.pid) {
if (WIFEXITED(status)) {
job.exitCode = WEXITSTATUS(status);
setJobState (job, js2Finished);
return;
} else if (WIFSIGNALED(status)) {
setJobState (job, js2Canceled);
return;
} else if (WIFSTOPPED(status)) {
if (ptrace (PTRACE_CONT, pid, NULL, NULL))
jdebug ("PTRACE_CONT failed for: %d (%s)\n", pid, strerror(errno));
}
}
/* ... */
}
Yes, the problem results from multi-threading. if monitorJob() runs in a seperate thread, ptrace(PTRACE_CONT) just fails. After moving it to the main thread (the one that called ptrace(PTRACE_ATTACH)), things go smoothly.

Video Renderer hangs in Directshow

I have created a filter graph manually in a Directshow experiment. Here, I have added a video source filter and a VMR-9 renderer. The Video Window of the Renderer does not move, minimize, close until the video reaches end of file. If I directly render the source filter, this does not occur. I need a solution to this.
while(1)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
IBaseFilter *pInputFileFilter = NULL;
IBaseFilter *pVideoRenderer = NULL;
IPin *pFileOut = NULL, *pVidIn = NULL;
IVideoWindow *VidWindow=NULL;
string s=openfilename();
wstring ws;
ws.assign (s.begin (), s.end ());
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return 1;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return 1;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// And add the filter to the filter graph
// using the member function AddFilter.
hr = pGraph->AddSourceFilter(ws.c_str(), ws.c_str(), &pInputFileFilter);
if (SUCCEEDED(hr))
{
// Now create an instance of the video renderer
// and obtain a pointer to its IBaseFilter interface.
hr = CoCreateInstance(CLSID_VideoMixingRenderer9,NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void **)&pVideoRenderer);
if (SUCCEEDED(hr))
{
hr = pGraph->AddFilter(pVideoRenderer, L"Video Renderer");
//pVideoRenderer->QueryInterface(IID_IVideoWindow,(void**)&VidWindow);
if (SUCCEEDED(hr))
{
// Now we need to connect the output pin of the source
// to the input pin of the renderer.
// Obtain the output pin of the source filter.
// The local function GetPin does this.
pFileOut = GetPin(pInputFileFilter, PINDIR_OUTPUT);
if (pFileOut != NULL)
{ // Is the pin good?
// Obtain the input pin of the WAV renderer.
// Obtain the input pin of the WAV renderer.
pVidIn = GetPin(pVideoRenderer, PINDIR_INPUT);
if (pVidIn != NULL)
{ // Is the pin good?
// Connect the pins together:
// We use the Filter Graph Manager's
// member function Connect,
// which uses Intelligent Connect.
// If this fails, DirectShow couldn't
// render the media file.
hr = pGraph->Connect(pFileOut, pVidIn);
}
}
}
}
}
if (SUCCEEDED(hr))
{
//VidWindow->put_FullScreenMode(OATRUE);
//VidWindow->put_Owner(NULL);
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
hr = pControl->Stop();
}
// Now release everything we instantiated--
// that is, if it got instantiated.
if(pFileOut)
{ // If it exists, non-NULL
pFileOut->Release(); // Then release it
}
if (pVidIn)
{
pVidIn->Release();
}
if (pInputFileFilter)
{
pInputFileFilter->Release();
}
if (pVideoRenderer)
{
pVideoRenderer->Release();
}
//VidWindow->Release();
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
Look into your code at the fragment:
// Do not use INFINITE in a real application, because it
// can block indefinitely.
This is where you are expected to add a message loop and dispatch messages. This is going to bring some awaited life into your application. You can poll for completion or register your window to receive a message when such completion occurs.

Resources