Related
I have a snippet of code which is somehow messing up the reading of bytes of a sqlite database. I've experienced this multiple times: first with a PNG where the last three bytes would differ, second with the king james bible and thirdly with a very simple test case. I'm stumped as to where I'm messing up. In all these cases, the command line sqlite tool can see the data inside the database correctly (both when viewed manually and when using writefile).
So the insertion is definitely working correctly, it's just that somehow my extraction is erroneous somehow. I am quite a novice at C so I expect I may have misallocated memory in someway, I just don't understand how.
#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
static char const dummy_content[] =
"hello world more \n\n\n hello worlds \nlalalala";
int
main(int argc, char **argv) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc, file_len, sqlite_len;
const char *file_contents;
const char *sqlite_contents;
rc = sqlite3_open("blah.db", &db);
if ( rc ) {
fprintf(stderr, "couldn't open db\n");
return 1;
}
/* initialise the schema */
rc = sqlite3_exec(db,
"BEGIN TRANSACTION;"
"DROP TABLE IF EXISTS blobs;"
"CREATE TABLE blobs(id TEXT NOT NULL, value BLOB, PRIMARY KEY(id));"
"COMMIT;",
NULL, NULL, NULL);
if ( rc ) {
fprintf(stderr, "couldn't initialise schema");
return 1;
}
file_contents = dummy_content;
file_len = sizeof(dummy_content);
/* insert the bytes */
rc = sqlite3_prepare_v2(db,
"INSERT INTO blobs VALUES(?, ?);",
-1,
&stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
printf("prepared stmt\n");
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
rc = rc | sqlite3_bind_blob(stmt, 2, file_contents, file_len, NULL);
if ( rc ) {
fprintf(stderr, "error binding to sql stmt");
return 1;
}
if ( (rc = sqlite3_step(stmt)) != SQLITE_DONE) {
fprintf(stderr, "something went wrong with execution");
}
sqlite3_finalize(stmt);
if ( rc != SQLITE_DONE ) return 1;
printf("loaded db\n");
/* load the bytes */
rc = sqlite3_prepare_v2(db,
"SELECT value FROM blobs WHERE id = ?;",
-1, &stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
if ( rc ) { fprintf(stderr, "error binding"); return 1; }
sqlite_len = -1;
while ( (rc = sqlite3_step(stmt)) != SQLITE_DONE ) {
if ( rc == SQLITE_ERROR ) {
fprintf(stderr, "error executing sql");
sqlite3_finalize(stmt);
return 1;
} else if ( rc == SQLITE_ROW ) {
sqlite_contents = sqlite3_column_blob(stmt, 0);
sqlite_len = sqlite3_column_bytes(stmt, 0);
}
}
if ( sqlite_len < 0 ) {
fprintf(stderr, "no value found in db");
sqlite3_finalize(stmt);
return 1;
}
printf("sqlite_len: %i file_len: %i\n", sqlite_len, file_len);
printf("from file string: %s\n", file_contents);
printf("from sqlite string: %s\n", sqlite_contents);
/* this frees the memory for the sqlite_contents */
sqlite3_finalize(stmt);
return 0;
}
You can only use the value returned by sqlite3_column_blob() until the next time you call sqlite3_step(). Your code isn't obeying that restriction (You're trying to print out the blob after another call to sqlite3_step() returns SQLITE_DONE)
From the documentation:
The pointers returned are valid until a type conversion occurs as described above, or until sqlite3_step() or sqlite3_reset() or sqlite3_finalize() is called.
I have written two process code both codes are copied below , let us assume sqlitep1.c refers to p1 and sqlitep2.c refers to p2
p1 constantly reads from database file sample.db and p2 writes to database file sample.db,
I executed one instances of p2 & p3 and one instances of p1, as per sqlite documentation, two process cannot simultaneously write to sqlite.
in code sqlitep2.c i have two version, one which opens connection and do write and then close (p2) and another version which opens connection and writes to db file and blocks with while(1), As shown in second version of sqlitep2.c which is executed as p3.
I first executed p3 and then p2, As per code p3 will block after writing, at this point I assume sqlite lock is not released as the connection is not closed.
But in my result I can see p2 is able to write without getting any busy error even though p3 has not released the lock.
Note : Executed in linux machine.
sqlitep1.c
#include <stdio.h>
#include </sqlite/sqlite3.h>
int main()
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char* pcSqlQuery = NULL;
char *name = NULL;
int retry_count = 0;
while (1)
{
printf ("process 1.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 1, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 1, opening failed....\n");
if (ret == SQLITE_BUSY)
{
printf ("process 1, open connection busy error....\n");
}
}
sleep(1);
}
printf ("process 1, database connection opened...\n");
/* prepare query */
ret = SQLITE_ERROR;
pcSqlQuery = "SELECT * FROM EMP";
while (ret != SQLITE_OK)
{
ret = sqlite3_prepare_v2 (pSqlHandle, pcSqlQuery, -1, &pSqlStmt, NULL);
if (ret == SQLITE_BUSY) {
printf ("process 1, prepare busy error....\n");
}
if (ret == SQLITE_ERROR) {
printf("SQLITE_ERROR\n");
}
sleep(1);
}
printf ("process 1, prepare success...\n");
/* extract result from query */
while(1)
{
ret = sqlite3_step (pSqlStmt);
if (ret == SQLITE_DONE)
break;
if (ret != SQLITE_ROW) {
printf("process 1, no row exists...\n");
break;
}
name = sqlite3_column_text (pSqlStmt, 1);
printf ("%s \n", name);
}
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
// while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 1, Finalizing %d...\n", ret);
// }
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
while (ret != SQLITE_OK && retry_count != 5) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
}
retry_count=0;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 1...\n");
return 0;
}
}
}
first version of sqlitep2.c which does not block after write operation( no while(1))
#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char pcSqlQuery[100] = "";
char *name = NULL;
int i = atoi(argv[1]);
int retry_count = 0;
while (1)
{
printf ("process 2.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 2, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 2, opening failed %d....\n", ret);
if (ret == SQLITE_BUSY)
{
printf ("process 2, open connection busy error....\n");
}
}
usleep(10*1000);
}
printf ("process 2, database connection opened...\n");
sqlite3_busy_timeout(pSqlHandle, 1000);
/* prepare query */
ret = SQLITE_ERROR;
char name[50];
while (ret != SQLITE_OK && retry_count != 10)
{
pSqlStmt = NULL;
sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
printf ("%s\n", pcSqlQuery);
ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1, &pSqlStmt, NULL);
sqlite3_bind_int(pSqlStmt, 1, i);
sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
if (ret == SQLITE_BUSY) {
printf ("process 2, prepare busy error....\n");
}
else {
if (ret == SQLITE_ERROR)
{
printf ("SQLITE_ERROR...\n");
}
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_step(pSqlStmt);
printf ("process 2, return from sqlite3_step : %d...\n", ret);
if (ret != SQLITE_DONE) {
printf ("process 2, insert error...\n");
} else if (ret == SQLITE_BUSY) {
printf("sqlite3_step busy error...\n");
} else {
i++;
ret = SQLITE_OK;
}
}
}
printf ("process 2, ret value of insert op %d\n ", ret);
usleep(10*1000);
retry_count++;
}
retry_count=0;
printf ("process 2, prepare success...\n");
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 2, Finalizing %d...\n", ret);
}
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
ret = sqlite3_close(pSqlHandle);
while (ret != SQLITE_OK) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
sleep(1);
}
retry_count=0;
pSqlHandle = NULL;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 2...\n");
return 0;
}
sleep(1);
}
}
Second version of sqlitep2.c which has a infinite block while(1) after write operation, which means it is not releasing the lock.
#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char pcSqlQuery[100] = "";
char *name = NULL;
int i = atoi(argv[1]);
int retry_count = 0;
while (1)
{
printf ("process 2.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 2, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 2, opening failed %d....\n", ret);
if (ret == SQLITE_BUSY)
{
printf ("process 2, open connection busy error....\n");
}
}
usleep(10*1000);
}
printf ("process 2, database connection opened...\n");
sqlite3_busy_timeout(pSqlHandle, 1000);
/* prepare query */
ret = SQLITE_ERROR;
char name[50];
while (ret != SQLITE_OK && retry_count != 10)
{
pSqlStmt = NULL;
sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
printf ("%s\n", pcSqlQuery);
ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1, &pSqlStmt, NULL);
sqlite3_bind_int(pSqlStmt, 1, i);
sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
if (ret == SQLITE_BUSY) {
printf ("process 2, prepare busy error....\n");
}
else {
if (ret == SQLITE_ERROR)
{
printf ("SQLITE_ERROR...\n");
}
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_step(pSqlStmt);
printf ("process 2, return from sqlite3_step : %d...\n", ret);
if (ret != SQLITE_DONE) {
printf ("process 2, insert error...\n");
} else if (ret == SQLITE_BUSY) {
printf("sqlite3_step busy error...\n");
} else {
i++;
ret = SQLITE_OK;
}
}
}
printf ("process 2, ret value of insert op %d\n ", ret);
usleep(10*1000);
retry_count++;
}
while (1) {} // block here, DO NOT proceed further.
retry_count=0;
printf ("process 2, prepare success...\n");
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 2, Finalizing %d...\n", ret);
}
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
ret = sqlite3_close(pSqlHandle);
while (ret != SQLITE_OK) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
sleep(1);
}
retry_count=0;
pSqlHandle = NULL;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 2...\n");
return 0;
}
sleep(1);
}
}
SQLite does locks around transactions, not open connections. Without an explicit transaction (which you don't appear to be doing) each SQL statement is a separate transaction that ends when the statement is executed. Your having an unfinalized statement means nothing, as "step" executed your INSERT and released the lock.
I try to make a ssh remote command with a part of code founded in libssh examples and i try to print output outside executing function like this
in int main();
printf("Server output: %s", nbytes);
int exec_uname(ssh_session session) {
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL) return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK) {
ssh_channel_free(channel);
return rc;
}
//Once a session is open, you can start the remote command with ssh_channel_request_exec():
rc = ssh_channel_request_exec(channel, "uname -a");
if (rc != SSH_OK) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
//If the remote command displays data, you get them with ssh_channel_read(). This function returns the number of bytes read. If there is no more data to read on the channel, this function returns 0, and you can go to next step. If an error has been encountered, it returns a negative value:
char buffer[256];
int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) {
if (fwrite(buffer, 1, nbytes, stdout) != nbytes) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
//Once you read the result of the remote command, you send an end-of-file to the channel, close it, and free the memory that it used:
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
You can't access a local variable outside a function. You either declare that in a broader scope, like global, which is a last-resort, or pass it in to be populated.
For example:
int exec_uname(ssh_session session, int* bytes) {
// ... code
// Push back to caller
*bytes = nbytes;
}
So when called:
int nbytes;
int result = exec_uname(session, &nbytes);
printf("Server output: %d", nbytes);
You'll still need to check result to be sure the function terminated properly or the value in nbytes will not be usable.
I'm having a problem with some openCL code I'm writing.
I've written a collection of utility functions to remove some boilerplate code from where I'm using it. The test method runs at the beginning and works absolutely fine, the code being below:
void openCLtest(char *arg_program, char *arg_device)
{
cl_int ret;
cl_device_id device_id = getDeviceId(atoi(arg_program), atoi(arg_device));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
cl_kernel kernel = compileCLkernel(&context, &device_id, "src/hello.cl", "hello");
cl_mem memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Allocate Buffer\n");
exit(1);
}
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to set kernel Arg\n");
exit(1);
}
ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue Task\n");
exit(1);
}
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for finish\n");
exit(1);
}
char string[MEM_SIZE];
ret = clEnqueueReadBuffer(queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char), string, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to read buffer\n");
exit(1);
}
printf("CL Produced: %s\n", string);
ret = clFlush(queue);
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Wait for test queue to finish\n");
exit(1);
}
ret = clReleaseKernel(kernel);
ret = clReleaseMemObject(memobj);
ret = clReleaseCommandQueue(queue);
ret = clReleaseContext(context);
}
This code works fine, and I then extracted the code into more functions which can be used for the real openCL I'm writing.
The same principle has been applied in the rest of the code, but this time, it doesn't work.
main:
openCLtest(argv[2], argv[3]); //This is the code above and works great
cl_device_id device_id = getDeviceId(atoi(argv[2]), atoi(argv[3]));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
....
double *coords_3D = cl_extrude_coords(&device_id, &context, &queue, coords_2D, nodes, LAYERS, LAYER_HEIGHT);
cl_extrude_coords:
double *cl_extrude_coords(cl_device_id* device_id, cl_context* context, cl_command_queue* queue, double *coords, int nodes, int layers, double layer_height)
{
cl_int ret;
cl_kernel extrude_coords = compileCLkernel(context, device_id, "src/OpenCL_Kernels/extrude_coords.cl", "extrude_coords");
cl_mem coords_2d = clCreateBuffer(*context, CL_MEM_READ_ONLY, sizeof(coords) / sizeof(coords[0]), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create coords_2d CL Buffer %d\n", ret);
exit(1);
}
cl_mem result = clCreateBuffer(*context, CL_MEM_WRITE_ONLY, sizeof(double) * nodes * 3 * layers, NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create result CL Buffer %d\n", ret);
exit(1);
}
ret = clEnqueueWriteBuffer(*queue, coords_2d, CL_TRUE, 0, sizeof(coords) / sizeof(coords[0]), (const void *)&coords, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed enqueue coords_2d write to buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 0, sizeof(cl_mem), (void *)&coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument coords_2d %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 1, sizeof(cl_mem), (void *)&result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument result CL Buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 2, sizeof(double), (void *)&layer_height);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument layers %d\n", ret);
exit(1);
}
size_t gWorkSize[] = {nodes, layers};
cl_event clEvent;
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, &clEvent);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Enqueue Extrude Coordinates Kernel\n");
exit(1);
}
double *res = (double *)malloc(sizeof(double) * nodes * 3 * layers);
ret = clFinish(*queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for queue to finish in extrude_coords %d\n", ret);
exit(1);
}
ret = clEnqueueReadBuffer(*queue, result, CL_TRUE, 0, sizeof(double) * nodes * 3 * layers, (void *)res, 1, &clEvent, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue the extrude_coords result buffer read %d\n", ret);
exit(1);
}
ret = clReleaseKernel(extrude_coords);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release kernel\n");
exit(1);
}
ret = clReleaseMemObject(coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
ret = clReleaseMemObject(result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
return res;
}
cl kernel:
#pragma OPENCL EXTENSION cl_khr_fp64: enable
__kernel void extrude_coords(__global const double * coords, __global double * res, const double layer_height){
uint i=get_global_id(0);
uint j=get_global_id(1);
uint layers=get_global_size(0);
res[3*(i*layers + j)] = coords[2*i];
res[3*(i*layers + j) + 1] = coords[2*i + 1];
res[3*(i*layers + j) + 2] = layer_height * j;
}
This function however, does not work, throwing the error below when clFinish(queue) is called.
Failed to wait for queue to finish in extrude_coords -36
Looking this up, I can see -36 is CL_INVALID_COMMAND_QUEUE. If I don't exit here, I then get an error thrown at the buffer read, error code -5, CL_OUT_OF_RESOURCES.
I'm not sure what is going wrong. The values of nodes and layers when this code is being tested are 151731 and 101 respectively. I'm not sure if that has something to do with it.
Does anyone have any ideas on what could be the issue and how to fix it, or even any suggestions on whether this structure for the code is a good idea. The plan was by passing the queue, context and device ID, each function can produce and execute its own kernel(s) to do something with the queue etc being released at the end of the program when they're no longer needed.
Any help would be appreciated, I've been stumped on this for several hours now.
EDIT:
I have since tried changinging the calling convention of clEnqueueNDRange in extrude_coords to
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize[0], NULL, 0, NULL, &clEvent);
as suggested in an answer but this does not work. Testing with printf("%d\n", &gWorkSize == &gWorkSize[0]); shows that the two pointers are functionally the same, so this is not the issue.
I then went on to modify the test openCL code to use clEnqueueNDRange instead of clEnqueueTask as follows:
size_t gWorkSize[] = {1, 1};
// ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
ret = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, NULL);
This still all works correctly, so something else is clearly wrong... I'm still not sure what...
The sizeof(coords) / sizeof(coords[0]) will not give the array size in C/C++. Best to use sizeof(coords)*elementsInCoords and pass in elementsInCoords. Alternatively, setup coords to be a std::vector<> and pass that around since you can get a data pointer out of it and the size as well.
Look at code:
size_t gWorkSize[] = {nodes, layers};
cl_event clEvent;
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, &clEvent);
&gWorkSize is of type size_t (*)[2], while argument must be of type const size_t*
Try this:
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, &gWorkSize[0], NULL, 0, NULL, &clEvent);
The loop was supposed to break but it keeps stuck on the fgets. process_P1 talks to inputHandler through a pipe. The problem is that inputHandler doesn't realize when process_P1 stops writing...the 'lalala' printf is never reached.
void process_P1(char *argv[], int fd[2], pid_t child)
{
int bytes = 0;
static char bufferIn[BUFFER_SIZE];
static char bufferOut[BUFFER_SIZE];
char line[BUFFER_SIZE];
// close reading end of pipe
close(fd[0]);
FILE *in = fopen(getInput(argv), "r");
FILE *out = fdopen(fd[1], "w");
if (in == NULL) {
sys_err("fopen(r) error (P1)");
}
int ret = setvbuf(in, bufferIn, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf error (P1)");
}
if (out == NULL) {
sys_err("fdopen(w) error (P1)");
}
ret = setvbuf(out, bufferOut, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf error (P1)");
}
while (fgets(line, BUFFER_SIZE, in) != NULL)
{
fprintf(out, "%s", line);
bytes += count(line) * sizeof(char);
}
// alert P2 to stop reading
//fprintf(out, "%s", STOP);
fclose(in);
fflush(out);
fclose(out);
printf("P1: file %s, bytes %d\n", getInput(argv), bytes);
// wait P2 ends
if (waitpid(child, NULL, 0) < 0) {
sys_err("waitpid error (P1)");
}
}
void *inputHandler(void *args)
{
int ret;
static char bufferIn[BUFFER_SIZE];
char line[BUFFER_SIZE];
struct node *iterator;
int *fd = (int*)args;
close(fd[1]);
FILE *in = fdopen(fd[0], "r");
if (in == NULL) {
sys_err("fdopen(r) error (P2)");
}
ret = setvbuf(in, bufferIn, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf(in) erro (P2)");
}
while (fgets(line, BUFFER_SIZE, in) != NULL)
{
// printf("%s", line);
iterator = firstArg;
while (iterator->next != NULL)
{
ret = sem_wait(&(iterator->sem));
if (ret == 0) {
strcat(iterator->buffer, line);
} else {
sys_err("sem_wait error");
}
ret = sem_post(&(iterator->sem));
if (ret != 0) {
sys_err("sem_post error");
}
iterator = iterator->next;
}
line[0] = '\0';
}
printf("lalala\n");
iterator = firstArg;
while (iterator->next != NULL)
{
ret = sem_wait(&(iterator->sem));
if (ret != 0) {
sys_err("sem_wait error");
}
iterator->shouldStop = 1;
ret = sem_post(&(iterator->sem));
if (ret != 0) {
sys_err("sem_post error");
}
iterator = iterator->next;
}
fclose(in);
return NULL;
}
The problem is probably not in the code you show. Since you mention a pipe, your problem is probably in the plumbing related to that — and most likely, you did a dup2() on one end of the pipe to make it into standard input or standard output, but you forgot to close the file descriptor that you duplicated, or you forgot to close the other end. The fgets() won't terminate until there's no process that could write to the pipe that it is reading from. If the process that is reading still has the write end of the pipe open, it will stay stuck in the read, waiting for it to write something.
So, look hard at your piping code. Make sure you've closed both the values returned by pipe() after you've duplicated one end to standard input or standard output.