Prepared SELECT statement executes but always returns 0 rows - mysql

I have read the documentation many times and i have searched on google and i found a lot of example and the code below is the result of my research.
But now i have a big problem and i don't find the solution to fix it.
The code below executes the query but doesn't display the result, it returns always 0 row while it have to return 2 rows... i don't understand where is the mistake.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
#define STRING_SIZE 50
#define SELECT_SAMPLE "select p.id_paz from pazienti p where p.id_doc = ?"
int main(void)
{
MYSQL *conn;
MYSQL_STMT *stmt;
MYSQL_BIND pbind[1],result[1]; /* results */
unsigned long length;
int row_count;
char login[STRING_SIZE];
my_bool is_null;
unsigned long plength;
char *pdata;
my_bool p_is_null;
// Open Database
const char *server = "localhost";
char *user = "root";
char *password = "password"; /* set me first */
char *database = "ProgettoSi";
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) {
//...
}
// Allocate statement handler
stmt = mysql_stmt_init(conn);
if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE)))
{
//...
}
fprintf(stdout, " prepare, SELECT successful\n");
plength = STRING_SIZE * sizeof(char);
p_is_null = 0;
pdata = (char*)malloc( STRING_SIZE * sizeof(char) );
/* STRING PARAMETER */
pbind[0].buffer_type= MYSQL_TYPE_STRING;
pbind[0].buffer= (char *)pdata;
pbind[0].buffer_length=STRING_SIZE * sizeof(char);
pbind[0].is_null= &p_is_null;
pbind[0].length= &plength;
if( mysql_stmt_bind_param( stmt, pbind ) ) {
//...
}
mysql_real_escape_string( conn, pdata, "123", strlen("123")*sizeof(char) );
plength = strlen( pdata ) + 1;
printf( "Executing query with parameters %s. \n", pdata);
/* Execute the SELECT query */
if (mysql_stmt_execute(stmt))
{
//...
}
/* Bind the result buffers for all 4 columns before fetching them */
result[0].buffer_type= MYSQL_TYPE_STRING;
result[0].buffer= (char *)login;
result[0].buffer_length= STRING_SIZE;
result[0].is_null= &is_null;
result[0].length= &length;
if (mysql_stmt_bind_result(stmt, result))
{
//...
}
if (mysql_stmt_store_result(stmt))
{
//...
}
row_count= 0;
fprintf(stdout, "Fetching results ...\n");
while (!mysql_stmt_fetch(stmt))
{
row_count++;
fprintf(stdout, " row %d\n", row_count);
/* column 2 */
fprintf(stdout, " column1 (string) : ");
if (is_null)
fprintf(stdout, " NULL\n");
else
fprintf(stdout, " %s(%ld)\n", login, length);
}
/* Validate rows fetched */
fprintf(stdout, " total rows fetched: %d\n", row_count);
/* Close the statement */
if (mysql_stmt_close(stmt))
{
//...
}
return 0;
}
It works if i insert manually the value in the query.
#define SELECT_SAMPLE "select p.id_paz from pazienti p where p.id_doc = 123"
if i execute this query and obviously comment the code in more... it works...

mysql_stmt_fetch has four possible return values: 0 (success), 1 (error), MYSQL_NO_DATA and MYSQL_DATA_TRUNCATED. Your loop terminates on anything other than success - but you don't check what actually happened. You might have 0 rows returned, or you might have some error condition best checked through mysql_stmt_errno() and mysql_stmt_error()...

Related

How to store a value from a MySQL database in a C variable

I'm starting with C and MySQL, I have created a database with some columns and I want to store two of them and use it in other parts of the code. In the example that I give i'm trying to store one value of "latitud" from de database in variable float lat, but it give me an error in the core. Do you know how can I solve this? Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#define HOST "localhost"
#define USER "victor"
#define PASS "tfg"
#define DATABASE "barcos"
int main (int argc, char *argv[]){
MYSQL *con;
MYSQL_ROW row;
MYSQL_RES *res;
con = mysql_init(NULL);
if (!mysql_real_connect(con, HOST, USER, PASS, DATABASE, 0, NULL, 0)){ // CONEXIÓN A LA BASE DE DATOS
fprintf(stderr, "%s\n", mysql_error(con));
return 1;
}
mysql_query(con, "SELECT latitud FROM BARCOS ");
res = mysql_store_result(con);
printf("latitud:\n");
while((row = mysql_fetch_row(res)) !=0)
printf("%s\n", row[0]);
float lat = row[0] ? atof(row[0]) : 0.0;
printf("%f", lat);
mysql_free_result(res);
mysql_close(con);
return 0;
}
What is res after
res = mysql_store_result(con); // res could be NULL, you do not check the result
Then you fetch all rows and print them
while((row = mysql_fetch_row(res)) !=0) // no braces, that means, ...
printf("%s\n", row[0]); // print only the first element from each row
but afterwards you call
//row is NULL here, because you exhausted the set in the loop before
float lat = row[0] ? atof(row[0]) : 0.0;
and you cannot dereference a NULL pointer.
From mysql_store_result:
Return Values
A pointer to a MYSQL_RES result structure with the results. NULL if the statement did not return a result set or an error occurred.
From mysql_fetch_row:
Return Values
A MYSQL_ROW structure for the next row, or NULL (either if there are no more rows or when an error occurred).

C - alternative using snprintf to prepare MySQL statements?

I've been tearing my hair out for a while on this one. The C code is called from a bash script, which loops through a command's output in a while loop and passes variables to the C script as args. It goes through a list and partitions data properly. I've been using the C MySQL api, and up until now everything has been relatively straight forward. It tries to run a SELECT(EXISTS) command to dictate whether to input a new row, or update an existing one.
I have typed the command into MySQL terminal and it works perfectly. I have even printf'd it and copied the command directly into the terminal. It works....
So why then, am I getting Syntax errors? I've tried escaping fields and input using backticks, single quotes and double quotes and I'm still getting this dumbounding error. I thought maybe it was something to do with the null space? But I'm at my witts end. Here's the code, any advice would be greatly appreciated :)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
const int MAXLEN = 100;
/* Compile with:
gcc db.connect.c `mysql_config --libs` -O1
for the best results
*/
/* Function definitions for later */
void finish_with_error(MYSQL *con);
int send_query(MYSQL *con, char query[MAXLEN]);
/* If any SQL commands fail, return an error message */
void finish_with_error(MYSQL *con)
{
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
/* Helper function to send queries to MySQL database */
int send_query(MYSQL *con, char query[MAXLEN])
{
if (mysql_query(con, query)) {
finish_with_error(con);
}
return 0;
}
int main(int argc, char ** argv)
{
// Establish MySQL API connection, if not- fail with err
MYSQL *con = mysql_init(NULL);
if (con == NULL) {
finish_with_error(con);
}
// Connection string.
if (mysql_real_connect(con, "localhost", "user", "password",
NULL, 0, NULL, 0) == NULL){
finish_with_error(con);
}
if (argv[1] == NULL){
printf("No query passed, terminating script \n");
return 1;
}
if (argv[1] != NULL) {
if( strcmp( argv[1], "--help" ) == 0 ) {
printf("This program was created to interact with MySQL, by checking and updating live network stats\n");
printf("It has 2 parameters, an IP address to look in the database for and a value to update a field by, \
if that IP address is found. ");
printf("If the value is not found, the program will insert a new row.");
return 1;
}
// Works out how much memory to allocate to buffer for snprintf
// Originally cmd_len was 65- as this was the amount of bits needed by the address string.
// This was changed to MAXLEN to prevent SEGFAULTS and give the function breathing room.
size_t cmd_len = MAXLEN;
size_t param_len = sizeof(argv[2]);
size_t q_len = cmd_len + param_len;
// Allocates that memory to a buffer, referenced as query
char *query = malloc(sizeof(char) * q_len);
snprintf(query, q_len, "SELECT EXISTS(SELECT * FROM `analytics`.`live` WHERE `foreign_addr` = `%s`)", argv[1]);
printf("%s\n", query);
send_query(con, query);
free(query);
// Used to store the result of the MySQL select commands
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL) {
finish_with_error(con);
}
// num_fields stores the number of fields, i and x are counters, answer is 1 or 0
int num_fields = mysql_num_fields(result);
int i = 0;
// Loops through each row in the answer statement.
// There will only be one row in the answer, which will be 1 or 0
// Basically, if the IP is found.
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))){
for (i=0; i<num_fields; i++) {
// If the IP isn't in the table
if(!atoi(row[i]))
send_query(con, argv[1]);
// If the IP is already in the table
if(atoi(row[i])) {
snprintf(query, q_len, "UPDATE analytics.live SET count=count+1 WHERE foreign_addr = '%s'", argv[1]);
printf("%s\n", query);
free(query);
snprintf(query, q_len, "UPDATE analytics.live SET dat_sent = dat_sent + %s", argv[2]);
printf("%s\n", query);
free(query);
}
}
}
mysql_close(con);
return 1;
}
mysql_close(con);
return 0;
}

MySQL C API parameterized query fetch result

I've been like 3 hours on this and I can't make this work.
I read MySQL C API documentation like 10 times about mysql_stmt functions.
What I need is like this: mysql_stmt_fetch()
The thing is I need a parametrized query because there is 1 user input.
Code is as follows:
char* regSol(char* token,MYSQL *conn){
char* regnr;
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
unsigned long str_length;
/*
* Validation
*/
stmt = mysql_stmt_init(conn);
char *sql="SELECT REGNR,Token FROM registed WHERE Token=?";
if(mysql_stmt_prepare(stmt,sql,strlen(sql))){
fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
memset(bind, 0, sizeof(bind)); //clears the structure.
bind[0].buffer= 0;
bind[0].buffer_length= 0;
bind[0].length= &str_length;
if(mysql_stmt_bind_result(stmt,bind))
{
fprintf(stderr, " mysql_stmt_bind_result(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
/*
fetch data
*/
unsigned long long nrow=0;
mysql_stmt_fetch(stmt);
if (str_length > 0)
{
char *data= (char*) malloc(str_length);
bind[0].buffer= data;
bind[0].buffer_length= str_length;
mysql_stmt_fetch_column(stmt, bind, 0, 0);
fprintf(stdout,"DEBUG !! - %s - !!\n",data);
}
return NULL;
}
I already tested mysql_stmt_bind_result and other functions.
The first try was preparing, binding and execute. fetch num of rows and it was always 0. No matter what, always 0.
Can anyone tell me the right way to get a result from a parametrized query?
EDIT 1:
new code that seems what will work but something is weird:
char* regSol(char* token,MYSQL *conn){
/*
* Needs to be completed. I have no idea why I can make this work
* Tested a lot of functions and got some SEGVs and 0 rows.
* And results that aren't even in the database
*/
char* regnr;
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
unsigned long str_length;
/*
* Validation
*/
stmt = mysql_stmt_init(conn);
char *sql="SELECT REGNR FROM registed WHERE Token=?";
if(mysql_stmt_prepare(stmt,sql,strlen(sql))){
fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
memset(bind, 0, sizeof(bind)); //clears the structure.
bind[0].buffer_type=MYSQL_TYPE_STRING;
bind[0].buffer=(char*)token;
bind[0].buffer_length=strlen(token)+1;
bind[0].length= &str_length;
if(mysql_stmt_bind_param(stmt,bind))
{
fprintf(stderr, " mysql_stmt_bind_param(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
if(mysql_stmt_execute(stmt)){
fprintf(stderr," mysql_stmt_execute(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
/*
fetch data
*/
//bind result
MYSQL_BIND resbind[1];
unsigned long reslen=0;
resbind[0].buffer=0;
resbind[0].buffer_length=0;
resbind[0].length=&reslen;
if(mysql_stmt_bind_result(stmt,resbind)){
fprintf(stderr," mysql_stmt_bind_result(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
mysql_stmt_fetch(stmt);
if (reslen > 0) //size of buffer?
{
char *data=(char*)malloc(reslen);
bind[0].buffer=data;
bind[0].buffer_length=reslen;
mysql_stmt_fetch_column(stmt, bind, 0, 0);
fprintf(stdout,"Result Len:%lu\nRegistation NR:%s",reslen,data);
free(data);
}
return "1";
}
The out is:
mysql_stmt_execute(), failed
Got packet bigger than 'max_allowed_packet' bytes
I think it's on here:
if(mysql_stmt_execute(stmt)){
fprintf(stderr," mysql_stmt_execute(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
So,I created MYSQL_BIND and prepare to bind params (input).
Then I executed. It makes an error which I don't know what It is.
I'm googling how I can access a char* to see the current sql query for troubleshooting.
I think, you have a couple of errors:
1) your query has one (input) parameter and 2 (output) columns, but your defining just one MYSQL_BIND, maybe for input parameter.
2) when you initialize:
bind[0].buffer= 0;
bind[0].buffer_length= 0;
bind[0].length= &str_length;
if this bind is for input parameter, you must change to:
bind[0].buffer= token;
bind[0].buffer_length= strlen(token) + 1;
and pass it with this call:
mysql_stmt_bind_param(stmt,bind);
3) where is your mysql_stmt_execute command? fetch dont work is your query is not executed
I dont check fetch code, but it looks like fine (notice me if not)

C program to add data to MYSQL database - No results added

I'm trying to build a C-program to add data to my MYSQL database and I would like to use variables within the SQL string. I want to insert UNIX time (epoch) in one column and the result from an energy meter into the other (double)
Even though it builds without errors or warnings I can't get it to insert the data into the table. Can someone give me a hint of where to look?
Thankful for all help I can get as I'm pretty much fumbling in the dark
Regards,
Mikael
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <mysql.h>
#include <my_global.h>
#include <stdlib.h> // For exit function
int loggingok; // Global var indicating logging on or off
double result = 323.234567; //Debug
double actual_time_sec;
void calculate_watts(void)
{
MYSQL *conn = mysql_init(NULL);
char *server = "localhost";
char *user = "root";
char *password = "password"; /* set me first */
char *database = "power";
char SQL_String[100];
char time_char[11];
char result_char[11];
time_t actual_time;
actual_time = time(0);
actual_time_sec = difftime(actual_time,0);
sprintf(time_char,"%g",actual_time_sec);
sprintf(result_char,"%g",result);
printf("Tid: %g\n",actual_time_sec); //Debug
printf("Resultat: %g\n", result); //Debug
strcpy(SQL_String, "INSERT INTO consumption(time,consumption) VALUES(");
strcat(SQL_String, time_char);
strcat(SQL_String, ",");
strcat(SQL_String, result_char);
strcat(SQL_String, ")");
printf("SQL: %s", SQL_String); //Debug
// SQL_String = "INSERT INTO consumption(time,consumption) VALUES('"+ actual_time_sec +"',"+ result +")";
if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1); }
if (mysql_query(conn, SQL_String)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1); }
}
int main (int argc, char *argv[])
{
printf(argv[1]); //Debug
if(strcmp(argv[1], "db")) {
loggingok=1;
printf("Efergy E2 Classic decode \n\n");
calculate_watts(); }
else {
loggingok=0; }
return 0;
}
here is a great example...
http://php.net/mysql_query. Note the usage of sprintf here. The 2nd and 3rd parameters work with the sprintf to place the data in these 2 parameters exactly where they are needed in the SQL statement.
$query = sprintf("SELECT firstname, lastname, address, age FROM friends
WHERE firstname='%s' AND lastname='%s'",
mysql_real_escape_string($firstname),
mysql_real_escape_string($lastname));
// Perform Query
$result = mysql_query($query);
// Check result
// This shows the actual query sent to MySQL, and the error. Useful for debugging.
if (!$result) {
$message = 'Invalid query: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
Please note the usage of if (!$result) this allows you to do a quick validation of if you have success or not. If an error is found the text resturned from mysql_error is placed in the message variable and then presented when the app dies.

C forking stops after 5 children

I am working on a C program which makes a connection to a database, grabs a list of devices, then forks the requests and creates an SSH connection to that device. The issue I am having is that, the query, which has 700 results, is always starting from the beginning after it hits 5 forks.
Essentially, I've looked into pthread and glibc to handle threading, but some of the examples I found did not work as desired, or added too much complexity.
The problem I am having is, it will stop at 5 children, and stop, instead of finishing the rest of the 700 devices.
Example code:
#include <libssh2.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <unistd.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <mysql.h>
/********************************
*
* gcc -o confmgr cfgmgr.c -Wall -lpthread -lz -lm -lrt -ldl -lssh2 $(mysql_config --cflags) $(mysql_config --libs) -std=gnu99
*
********************************/
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
struct timeval timeout;
int rc;
fd_set fd;
fd_set *writefd = NULL;
fd_set *readfd = NULL;
int dir;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(socket_fd, &fd);
/* now make sure we wait in the correct direction */
dir = libssh2_session_block_directions(session);
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
readfd = &fd;
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
writefd = &fd;
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
return rc;
}
int *connect_to_device(MYSQL_RES** args){
printf("%s", args[2]);
const char *hostname = "1.1.1.1";
const char *commandline = "command_to_run ";
const char *username = "static_user";
const char *password = "static_pass";
unsigned long hostaddr;
int sock;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
char *exitsignal=(char *)"none";
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
hostaddr = inet_addr(hostname);
/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the
* connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance */
session = libssh2_session_init();
if (!session)
return -1;
/* tell libssh2 we want it all done non-blocking */
libssh2_session_set_blocking(session, 0);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_handshake(session, sock)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
libssh2_trace(session, LIBSSH2_TRACE_TRANS | LIBSSH2_TRACE_KEX | LIBSSH2_TRACE_AUTH | LIBSSH2_TRACE_CONN | LIBSSH2_TRACE_SCP | LIBSSH2_TRACE_SFTP | LIBSSH2_TRACE_ERROR | LIBSSH2_TRACE_PUBLICKEY );
/* Exec non-blocking on the remove host */
while( (channel = libssh2_channel_open_session(session)) == NULL &&
libssh2_session_last_error(session,NULL,NULL,0) == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( channel == NULL )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
while( (rc = libssh2_channel_exec(channel, commandline)) == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
for( ;; )
{
// loop until we block
int rc;
do
{
char buffer[0x4000];
/* strange thing */
sleep( 1 );
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
for( i=0; i < rc; ++i )
putchar( buffer[i] );
}
}
while( rc > 0 );
// this is due to blocking that would occur otherwise so we loop on this condition
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else if( rc == 0 )
break;
}
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
;
if( rc == 0 )
{
//does-not-work if( libssh2_channel_wait_closed(channel) == 0 )
exitcode = libssh2_channel_get_exit_status( channel );
}
printf("\n%d\n", 221 );
libssh2_channel_free(channel);
channel = NULL;
/***********************/
shutdown:
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
close(sock);
fprintf(stderr, "\n----------------------\nScript Finished\n\n");
libssh2_exit();
return 7;
}
/********************************
*
*
*
*
********************************/
int main(int argc, char *argv[]){
pid_t childPID;
int children = 0;
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
char *mySQLserver = "localhost";
char *mySQLuser = "root";
char *mySQLpassword = ""; /* set me first */
char *mySQLdatabase = "Devices";
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, mySQLserver,
mySQLuser, mySQLpassword, mySQLdatabase, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
/* send SQL query */
if (mysql_query(conn, "SELECT Hostname,Descr,IP,Username,Password FROM All_Active_Devices")) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_use_result(conn);
/* output table name */
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(res)) != NULL){
printf("%s \n", row[0]);
children++; // Last fork() was successful
while (children >= 5)
{
int status;
// Wait for one child to exit
if (wait(&status) == 7)
{
children--;
}
}
childPID = fork ();
if (childPID < 0) {
printf("Fork Error \n");
} else if (childPID == 0) {
printf("\tCreating Fork for %s: pid %d \n", row[0], childPID);
connect_to_device ( &row );
}
else{
printf("\tDid not create Fork for %s \n", row[0]);
}
}
/* close connection */
mysql_free_result(res);
mysql_close(conn);
return 0;
}
Your child processes are exitting - in particular not with exit status 7 - you have a return in your connect_to_device function, but that is ignored, and each child starts going round the loop, creating more children.
You probably want: return connect_to_device ( &row ); instead.
wait() returns the child PID that died, not its status - which is in WEXITSTATUS(status).
What happens after connect_to_device returns? It looks like that thread will also start in on the while loop as I don't see that child process exiting, sitting you in the while children >=5 loop. The 5 in your condition and 5 threads isn't a coincidence.
Some output from a run would be helpful, also paring down the code.
Try to get your scaffolding working, without the ssh code. Just getting the processes to stop and start shouldn't need ssh. Then add in the application logic once you're sure the underlying support works.
Perhaps ServerAliveCountMax is getting in the way:
EDIT FROM NETCODER BELOW
ServerAliveCountMax
Sets the number of server alive messages (see
below) which may be sent without ssh(1) receiving any messages back
from the server. If this threshold is reached while server alive
messages are being sent, ssh will disconnect from the server,
terminating the session. It is important to note that the use of
server alive messages is very different from TCPKeepAlive (below). The
server alive messages are sent through the encrypted channel and
therefore will not be spoofable. The TCP keepalive option enabled by
TCPKeepAlive is spoofable. The server alive mechanism is valuable when
the client or server depend on knowing when a connection has become
inactive.
The default value is 3. If, for example, ServerAliveInterval (see
below) is set to 15 and ServerAliveCountMax is left at the default, if
the server becomes unresponsive, ssh will disconnect after
approximately 45 seconds. This option applies to protocol version 2
only.
See the man page for ssh_config (man 5 ssh_config) for details.