Semaphore values are not changing in Ubuntu - c

I'm trying to create a solution for the River Crossing Problem from "The Little Book of Semaphores" (Chapter 5, section 7, page 148), I'm using an Ubuntu virtual machine in my PC.
The problem is that the semaphores I created are not changing values, all of them stay at 0, I'm using four files.
What I do is, run buffer and then create two hacker processes and then two serf processes, the thing is that the "Boarding a X" message is printed before the boat is filled (at least four passengers) and when I print the semaphore values all of them are in 0.
header.h, where I declare Semaphore ids and operations:
#ifndef SEMAFOROS_H
#define SEMAFOROS_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define BARRIER 10
#define MUTEX 11
#define SERFQUEUE 12
#define HACKERQUEUE 13
struct buffer {
int hackers;
int serfs;
};
int sem_wait(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = -val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int sem_signal(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int mutex_wait(int semid, int sem_num) {
return sem_wait(semid, sem_num, 1);
}
int mutex_signal(int semid, int sem_num) {
return sem_signal(semid, sem_num, 1);
}
#endif
buffer.c, where I create the semaphores:
#include "header.h"
int main(int argc, char* argv[])
{
int semid, shmid, i;
key_t key;
if (argc != 1) {
printf("usage: %s\n", argv[0]);
return -1;
}
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(argv[0]);
return -1;
}
if ( (semid = semget(key, 4, 0666 | IPC_CREAT)) < 0 ) {
perror(argv[0]);
return -1;
}
semctl(semid, BARRIER, SETVAL, 4);
semctl(semid, MUTEX, SETVAL, 1);
semctl(semid, SERFQUEUE, SETVAL, 0);
semctl(semid, HACKERQUEUE, SETVAL, 0);
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
if ( (shmid = shmget(key, sizeof(struct buffer), 0666 | IPC_CREAT)) < 0) {
semctl(semid, 0, IPC_RMID, 0);
perror("shmget");
return -1;
}
struct buffer *b = (struct buffer *) shmat(shmid, (void *) 0, 0);
b->hackers = 0;
b->serfs = 0;
shmdt(b);
return 0;
}
hackers.c, code for hackers:
#include "header.h"
#include <time.h>
void a_hacker(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->hackers += 1;
if (b->hackers == 4) {
sem_signal(semid, HACKERQUEUE, 4);
b->hackers = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->hackers = 0;
b->serfs -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, HACKERQUEUE, 1);
printf("Boarding a hacker\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_hackers = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_hackers = atoi(argv[1]);
if (amount_hackers < 1) {
printf("%s: The amount_of_hackers must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_hackers; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_hacker(argv[0]);
} else {
}
}
return 0;
}
serfs.c, code for serfs:
#include "header.h"
#include <time.h>
void a_serf(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->serfs += 1;
if (b->serfs == 4) {
sem_signal(semid, SERFQUEUE, 4);
b->serfs = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->serfs = 0;
b->hackers -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, SERFQUEUE, 1);
printf("Boarding a serf\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_serfs = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_serfs = atoi(argv[1]);
if (amount_serfs < 1) {
printf("%s: The amount_of_serfs must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_serfs; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_serf(argv[0]);
} else {
}
}
return 0;
}
Can someone please help me?

Related

tail exec doesn't work well in pipe (No output until parent process die!)

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
int pipFd[1000][2], hasPipe, forked, pipNum = 0, pNum = 0, bPipe = 0, bpipFd[2], stPipe, InpToChld = 0;
pid_t pid[1000];
void * outInp;
int builtin_command(char **argv)
{
if (!strcmp(argv[0], "quit")) /* quit command */
exit(0);
if (!strcmp(argv[0], "&")) /* Ignore singleton & */
return 1;
return 0; /* Not a builtin command */
}
int parsecmd(char *buf, char **argv)
{
char *delim; /* Points to first space delimiter */
int argc; /* Number of args */
int bg; /* Background job? */
buf[strlen(buf) - 1] = ' '; /* Replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* Ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
while ((delim = strchr(buf, ' ')))
{
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ' || *buf == '<')) /* Ignore spaces */
buf++;
}
argv[argc] = NULL;
if (argc == 0) /* Ignore blank line */
return 1;
/* Should the job run in the background? */
if ((bg = (*argv[argc - 1] == '&')) != 0)
argv[--argc] = NULL;
return argc;
}
void myExec(char **argv, char *buf)
{
// if ((pid[pNum] = fork()) == 0)
// {
strcpy(buf, "/bin/");
buf[5] = 0;
strcat(buf, argv[0]);
//printf("%s\n", buf);
if (execv(buf, argv) < 0)
{
memset(buf, 0, 255);
strcpy(buf, "/usr/bin/");
strcat(buf, argv[0]);
if (execv(buf, argv) < 0)
{
printf("exec failed\n");
exit(-1);
}
}
exit(0);
// }
// else
// wait(NULL);
}
int splitPipe(char **cmdLine)
{
static char *svBuftok;
if (!hasPipe)
*cmdLine = strtok_r(*cmdLine, "|", &svBuftok);
else{
//printf("--------%s\n", svBuftok);
*cmdLine = strtok_r(svBuftok, "|", &svBuftok);
}
//printf(".......................%s %s\n", svBuftok, *cmdLine);
return strlen(svBuftok);
}
int isDigit(char * strings){
int i, tmp = strlen(strings);
for(i = 0; i < tmp; i++){
if(strings[i] < '0' || strings[i] > '9') return 0;
}
return 1;
}
void handler(int sig)
{
if (sig == SIGINT && forked) exit(0);
}
static char *getcmd()
{
static char buf[256];
//fputs("> ", stdout);
//printf("asdfasdfasdf\n");
fflush(stdin);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
return NULL;
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = 0;
return buf;
}
int main()
{
char *cmdline;
char *argv[12000];
char c, dir[256], buf[256], rdBuf[100000], pipBuf[100000];
int status, fd, rfd, dest, argc;
pid_t tmpPid;
getcwd(dir, 256);
signal(SIGINT, handler);
signal(SIGTSTP, handler);
signal(SIGCHLD, handler);
signal(30, handler);
//outInp = &&Outinp;
//printf("gd\n");
while (cmdline = getcmd())
{
ret:
do
{
rfd = 0;
hasPipe = splitPipe(&cmdline);
//printf(":::::::::::::::%s %d\n", cmdline, hasPipe);
if (strlen(cmdline) <= 1)
continue;
argc = parsecmd(cmdline, argv);
if (!builtin_command(argv))
{
if(!strcmp(argv[0], "exit")) exit(0);
{
if(hasPipe) pipe(pipFd[pNum]);
if(!bPipe) pipe(bpipFd);
fflush(NULL);
if((pid[pNum] = fork()) == 0){
int ofd, svStdout = dup(1), svStin = dup(0);
forked = 1;
close(pipFd[pNum][0]);
//printf("%s %d\n",argv[0], getpid());
//fflush(stdout);
//printf("\n");
if(bPipe) {
close(pipFd[pNum - 1][1]);
dup2(pipFd[pNum - 1][0], STDIN_FILENO);
}
else{
close(bpipFd[1]);
dup2(bpipFd[0], STDIN_FILENO);
}
//addArgv(pipBuf, &argc, argv);
if(hasPipe) dup2(pipFd[pNum][1], 1);
if(!strcmp(argv[argc - 2], ">")){
//printf("chked %s\n", argv[argc - 1]);
remove(argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY | O_CREAT, 0755);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
else if(!strcmp(argv[argc - 2], ">>")){
//printf("chked %s\n", argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
fflush(stdout);
myExec(argv, buf);
close(pipFd[pNum][1]);
if(bPipe) {
close(pipFd[pNum - 1][0]);
}
else{
close(bpipFd[0]);
}
dup2(svStin, 0);
dup2(svStdout, 1);
if(!strcmp(argv[argc - 2], ">")) close(ofd);
exit(0);
}
else{
if(!bPipe) {
close(bpipFd[0]);
stPipe = pid[pNum];
InpToChld = 1;
}
pNum++;
}
}
bPipe = hasPipe;
}
}while (hasPipe);
while(InpToChld){
memset(rdBuf, 0, sizeof(rdBuf)); int i;
fflush(NULL);
//printf("Inp~~\n");
if(read(0, rdBuf, sizeof(rdBuf)) == 0){
write(bpipFd[1], "\0", 1);
InpToChld = 0;
break;
}
if(write(bpipFd[1], rdBuf, strlen(rdBuf)) < 0){
cmdline = rdBuf;
InpToChld = 0;
goto ret;
}
fflush(NULL);
//fflush(stdout);
}
}
}
At first, exec to tail works well.
But tail's output doesn't be printed until parent process die.
for example, cat < /proc/meminfo | head works well
but cat < /proc/meminfo | tail is printed after exit parent.
I guess this is about input / output problem, but I can't solve this problem.
The steps to code a tiny shell :
handle SIGCHLD
if necessary handle redirect
if necessary handle pipe
The following code could work, not handle builtin command:
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_SIGCHLD_handle(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
int main()
{
char buf[256];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
if (fork() > 0) { // parent
wait(NULL);
continue;
}
//child
// handle SIGCHLD
struct sigaction act;
act.sa_handler = signal_SIGCHLD_handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &act, NULL);
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = '\0';
for (char* next_cmd = strtok(buf, "|"); next_cmd != NULL; ) {
char* current_cmd = next_cmd;
next_cmd = strtok(NULL, "|");
char* argv[10];
int argv_index = 0;
int new_argv = 1;
for (;;) {
if(*current_cmd == '\0') {
argv[argv_index] = NULL;
break;
}
if (isspace(*current_cmd)) {
*current_cmd++ = '\0';
new_argv = 1;
continue;
}
if (*current_cmd == '<') {
++current_cmd;
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf("Please use cmd < file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("<");
return -1;
}
dup2(fd, 0);
close(fd);
continue;
}
if (*current_cmd == '>') {
int add = 0;
if (*++current_cmd == '>') {
add = 1;
++current_cmd;
}
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf(add == 0 ? "Please use cmd > file_name" : "Please use cmd >> file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, add == 0 ? (O_WRONLY|O_CREAT) : (O_WRONLY|O_CREAT|O_APPEND), 0644);
if (fd < 0) {
perror(add == 0 ? ">" : ">>");
return -1;
}
dup2(fd, 1);
close(fd);
continue;
}
if (new_argv == 1) {
new_argv = 0;
argv[argv_index++] = current_cmd;
}
++current_cmd;
}
if (argv_index == 0)
continue;
if (next_cmd != NULL) {
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(pipe_fd[0]);
dup2(pipe_fd[1], STDOUT_FILENO);
close(pipe_fd[1]);
execvp(argv[0], argv);
return -1;
}
close(pipe_fd[1]);
dup2(pipe_fd[0], STDIN_FILENO);
close(pipe_fd[1]);
continue;
}
execvp(argv[0], argv);
}
}
return 0;
}

TCP server not waiting for client response?

I have been given the task to write a Roulette game, using TCP socket programming in C.
The code was working just fine, until I got close to finishing it, and for some unknown reason, it stopped working properly and I can't track down the error.
The code used to work with simple recv() calls, so I tried making the readn() function (actually got it from another post), however it did not solve the issue.
I might be overlooking the problem, which lies in the for (int i = 0 ; i < max_round ; i++) loop of the main() function.
Here is my server:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
int
readn(int f, void *av, int n)
{
char *a;
int m, t;
a = av;
t = 0;
while(t < n){
m = read(f, a+t, n-t);
if(m <= 0){
if(t == 0)
return m;
break;
}
t += m;
}
return t;
}
typedef struct
{
int _count, _bet, _client, _currency;
int _numbers[3];
char *_color;
} Roulette;
int find_element(int searched, int numbers[], int count)
{
for (int i = 0; i < count; i++)
{
if (searched == numbers[i])
return 1;
}
return 0;
}
void Round_Results(Roulette *obj1, Roulette *obj2, const int size)
{
char *lose_msg = "Sajnos nem nyert ebben a korben!\n";
char *win_msg = "Gratulalok, ebben a korben nyert!\n";
char answer[size];
srand(time(NULL));
int winner_number = rand() % 10;
if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
{
send(obj1->_client, lose_msg, size, 0);
obj1->_currency = obj1->_currency - obj1->_bet;
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, lose_msg, size, 0);
obj2->_currency = obj2->_currency - obj2->_bet;
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
{
send(obj1->_client, win_msg, size, 0);
obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, lose_msg, size, 0);
obj2->_currency = obj2->_currency - obj2->_bet;
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
{
send(obj1->_client, lose_msg, size, 0);
obj1->_currency = obj1->_currency - obj1->_bet;
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, win_msg, size, 0);
obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj2->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
{
send(obj1->_client, win_msg, size, 0);
obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, win_msg, size, 0);
obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj1->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
}
void Initialize(int client, int count, int numbers[], int bet, char *color, Roulette *obj)
{
obj->_client = client;
obj->_count = count;
obj->_color = color;
obj->_bet = bet;
for (int i = 0; i < count; i++)
obj->_numbers[i] = numbers[i];
}
void Round_Information(int client, const int size, Roulette *obj)
{
char *message = malloc(size);
char *money_msg = "Mennyi zsetonba fogad?\n";
char *number_msg = "Melyik szamra fogad?\n[0-9]\n";
char *count_msg = "Mennyi szamra fogad?\n[1-3]\n";
char *color_msg = "Milyen szinre fogad?\n[black/red]\n";
int count = 0;
char *color;
int numbers[3];
int bet;
//Bet
send(client, money_msg, size, 0);
readn(client,message,size);
bet = atoi(message);
//Count
send(client, count_msg, size, 0);
readn(client,message,size);
count = atoi(message);
//Number/Numbers
for (int i = 0; i < count; i++)
{
send(client, number_msg, size, 0);
readn(client,message,size);
numbers[i] = atoi(message);
}
//Color
send(client, color_msg, size, 0);
readn(client,message,size);
color = message;
Initialize(client, count, numbers, bet, color, obj);
free(message);
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
exit(-1);
}
const int size = 50;
int max_round, starting_money;
int flag = 0;
int on = 1;
char *message = malloc(size);
char *round_msg = "Korok szama :\n";
char *greeting_msg = "Sikeresen csatlakozott a szerverre!\n";
char *waiting_msg = "A masik jatekosra varunk!\n";
char *win_msg = "Gratulalok !\nMegnyerte a jatekot!\n";
char *lose_msg = "Jatek vege !\nSajnos nem nyert!\n";
Roulette *obj1 = malloc(size);
Roulette *obj2 = malloc(size);
int server_socket = socket(AF_INET, SOCK_STREAM, flag);
if (server_socket < 0)
{
printf("Nem sikerult a socket-et letrehozni\n");
exit(-1);
}
struct sockaddr_in server_adress;
server_adress.sin_addr.s_addr = INADDR_ANY;
server_adress.sin_family = AF_INET;
server_adress.sin_port = atoi(argv[1]);
setsockopt(server_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
int binding_server = bind(server_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
if (binding_server < 0)
{
printf("nem sikerult bindolni a szervert!\n");
exit(-1);
}
listen(server_socket, 2);
int client1 = accept(server_socket, NULL, NULL);
int client2 = accept(server_socket, NULL, NULL);
send(client1, greeting_msg, size, flag);
send(client2, greeting_msg, size, flag);
printf("Milyen hosszu legyen a jatek ? (Hany kor)\n");
scanf("%s", message);
max_round = atoi(message);
//Korok szama
send(client1, message, size, flag);
send(client2, message, size, flag);
printf("Mennyi zsetonnal kezdodjon a jatek?\n");
scanf("%s", message);
starting_money = atoi(message);
//Kezdo penz
send(client1, message, size, flag);
send(client2, message, size, flag);
obj1->_currency = starting_money;
obj2->_currency = starting_money;
for (int i = 0; i < max_round; i++)
{
Round_Information(client1, size, obj1);
Round_Information(client2, size, obj2);
Round_Results(obj1, obj2, size);
}
if (obj1->_currency > obj2->_currency)
{
send(obj1->_client, win_msg, size, flag);
send(obj2->_client, lose_msg, size, flag);
}
else if (obj1->_currency < obj2->_currency)
{
send(obj2->_client, win_msg, size, flag);
send(obj1->_client, lose_msg, size, flag);
}
else
{
send(obj1->_client, lose_msg, size, flag);
send(obj2->_client, lose_msg, size, flag);
}
close(client1);
close(client2);
close(server_socket);
free(message);
free(obj1);
free(obj2);
return 0;
}
Here is the Client:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
void Round_Information(int client, const int size, int currency)
{
char *message = malloc(size);
char answer[size];
char *black = "black";
char *red = "red";
int count = 0;
memset(answer, 0, size);
//Bet
recv(client, message, size, 0);
if (currency == 0)
{
printf("Game over!\nVeszitett!\n");
close(client);
}
while (atoi(answer) < 1 || atoi(answer) > currency)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
answer[0] = '0';
//Count
recv(client, message, size, 0);
while (atoi(answer) < 1 || atoi(answer) > 3)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
count = atoi(answer);
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
//Number/Numbers
for (int i = 0; i < count; i++)
{
recv(client, message, size, 0);
answer[0] = 'z';
while (atoi(answer) <= 0 || atoi(answer) > 9)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
}
//Color
recv(client, message, size, 0);
while ((strcmp(answer, black) != 0) && (strcmp(answer, red) != 0))
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
free(message);
}
void Round_Results(int client_socket, char *message, const int size, int *currency)
{
recv(client_socket, message, size, 0);
printf("%s\n", message);
recv(client_socket, message, size, 0);
(*currency) = atoi(message);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
exit(-1);
}
const int size = 50;
int flag = 0;
int max_round, currency;
int on = 1;
char message[size];
int client_socket = socket(AF_INET, SOCK_STREAM, flag);
if (client_socket < 0)
{
printf("Nem sikerult a socketet letrehozni!\n");
exit(-1);
}
struct sockaddr_in server_adress;
server_adress.sin_addr.s_addr = INADDR_ANY;
server_adress.sin_family = AF_INET;
server_adress.sin_port = atoi(argv[1]);
setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
int connection = connect(client_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
if (connection < 0)
{
printf("Nem sikerult kapcsolodni a szerverhez!\n");
exit(-1);
}
//Sikeres kapcsolodas
int receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("%s", message);
//Korok szama
receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("Korok szama :%s\n", message);
max_round = atoi(message);
//Kezdo penz
receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("Jelenlegi zsetonok mennyisege :%s\n", message);
currency = atoi(message);
for (int i = 0; i < max_round; i++)
{
Round_Information(client_socket, size, currency);
Round_Results(client_socket, message, size, &currency);
printf("Jelenlegi zseton :%d\n", currency);
}
recv(client_socket, message, size, flag);
printf("%s\n", message);
close(client_socket);
return 0;
}
It was not easy to read, since i do not know what the outputs mean, but i think i found your problem.
if (strcmp(answer, "befejeztem"))
{
close(client);
}
strcmp is 0 when the strings are equal. That means in almost every case you close the socket. Actually in the first loop answer is zero that means you are closing the socket right away. If you close the socket but the server tries to send data the program will receive the SIGPIPE signal and i think the default handler will just abort the program.
Try to change all these if statements to:
if(!strcmp(answer, "befejeztem"))
{
close(client);
}

function does not return value in c

I have a behaviour that I don't understand.
When I call function get_bloccante_multimsg(...) doesn't return anything, read_m variable is not valorised and the next instruction is not executed.
The code below is a subpart of the program, hope that is helpful to identify the problem.
buffer.h
msg_t* get_bloccante_multimsg(int buffer, int C_id, int semid, const int N);
buffer.c
msg_t* get_bloccante_multimsg(int buffer, int C_id, int semid, const int N)
{
char* string;
char* shared_memory;
int *Cindex;
struct shmid_ds shmbuffer;
sb.sem_num = PIENE;
sb.sem_op = -1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore P(PIENE)");
exit(-9);
}
sb.sem_num = USO_T;
sb.sem_op = -1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore P(USO_T)");
exit(-9);
}
Cindex = shmat(C_id, NULL, 0);
shmctl(buffer, IPC_STAT, &shmbuffer);
shared_memory = (char *) shmat(buffer, (void *)0, 0);
memcpy(string, &shared_memory[*Cindex*20], 20);
*Cindex = (*Cindex + 1) % N;
shmdt(Cindex);
shmdt(shared_memory);
sb.sem_num = USO_T;
sb.sem_op = 1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore V(USO_T)");
exit(-9);
}
sb.sem_num = VUOTE;
sb.sem_op = 1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore V(VUOTE)");
exit(-9);
}
return msg_init_string(string);
}
main.c
msg_t *read_m;
for (int i = 0; i < C; i++)
{
// fork consumatore
cons_pid[i] = fork();
switch(cons_pid[i]) {
case -1: // fork fallita
exit(-5);
break;
case 0:
read_m = get_bloccante_multimsg(segment_id, C_id, semid, N);
printf("Messaggio in array: %s", (char *)getMessage(read_m));
exit(0);
break;
default:
break;
}
}
Thanks for your help.
In the function get_bloccante_multimsg(), the pointer to char string is used uninitialized in the line:
memcpy(string, &shared_memory[*Cindex*20], 20);
and later at:
return msg_init_string(string);
This leads to undefined behavior. You need to allocate space for the string and assign the address to string.

Process communication with semaphore in C

I'm writing two files:
a father.c with a parent process, and a son.c with a child process. They should use semaphore for synchronization. When I launch the father (compiled), the father process waits forever after the child process message:
Child ftok done.
father.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
typedef union _semun {
int val;
struct semid_ds *buf;
ushort *array;
} semun;
int initsem(key_t key){
int status = 0, semid;
semid = semget(key, 1, 0600 | IPC_CREAT | IPC_EXCL);
if(semid == -1){
if(errno == EEXIST){
semid = semget(key, 1, 0);
}
else{
semun arg;
arg.val = 1;
status = semctl(semid, 0, SETVAL, arg);
}
if(semid == -1 || status == -1){
perror("initsem failed\n");
return -1;
}
return (semid);
}
}
int waitSem(int semid) {
struct sembuf wait_buf;
wait_buf.sem_num = 0;
wait_buf.sem_op = -1;
if(semop(semid, &wait_buf, 1) == -1) {
perror("waitSem failed");
exit(1);
}
return(0);
}
int signalSem(int semid) {
struct sembuf signal_buf;
signal_buf.sem_num = 0;
signal_buf.sem_op = 1;
if(semop(semid, &signal_buf, 1) == -1) {
perror("signalSem failed");
exit(1);
}
return(0);
}
int main(){
pid_t pid;
key_t key;
int semid;
if(key = ftok("/home/user/Scrivania/test.txt", 'a') == -1){
perror("IPC error: ftok\n");
exit(1);
}
else{
printf("Ftok done\n");
}
semid = initsem(key);
pid = fork();
if(pid < 0){
printf("failed fork()\n");
}
else if(pid == 0){
printf("Child process with PID: %d\n", pid);
execl("/home/user/Desktop/son", "son", "",(char *)0);
}
else{
printf("Father process with PID: %d\n", pid);
printf("Waiting for my son\n");
waitSem(semid);
printf("My son has done\n");
signalSem(semid);
}
return 0;
}
son.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
typedef union _semun {
int val;
struct semid_ds *buf;
ushort *array;
} semun;
int initsem(key_t key){
int status = 0, semid;
semid = semget(key, 1, 0600 | IPC_EXCL);
if(semid == -1){
if(errno == EEXIST){
semid = semget(key, 1, 0);
}
else{
semun arg;
arg.val = 1;
status = semctl(semid, 0, SETVAL, arg);
}
if(semid == -1 || status == -1){
perror("initsem failed\n");
return -1;
}
return (semid);
}
}
int waitSem(int semid) {
struct sembuf wait_buf;
wait_buf.sem_num = 0;
wait_buf.sem_op = -1;
if(semop(semid, &wait_buf, 1) == -1) {
perror("waitSem failed");
exit(1);
}
return(0);
}
int signalSem(int semid) {
struct sembuf signal_buf;
signal_buf.sem_num = 0;
signal_buf.sem_op = 1;
if(semop(semid, &signal_buf, 1) == -1) {
perror("signalSem failed");
exit(1);
}
return(0);
}
int main(){
pid_t pid;
key_t key;
int semid;
if(key = ftok("/home/user/Desktop/test.txt", 'a') == -1){
perror("IPC error: ftok\n");
exit(1);
}
else{
printf("Ftok done\n");
}
semid = initsem(key);
waitSem(semid);
printf("Pre signal\n");
signalSem(semid);
printf("My operation\n");
return 0;
}

why this linux pseudo terminal program doesn't work?

Master reads input from stdin and writes to pty-master, slave reads input from pty-slave and writes to stdout.
But this code/program seems doesn't work.
The Master writes to pty-master is OK, but the slave hungs when reads from pty-slave.
anyone can help me? thx in advance.
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
/*
* copy from apue
*/
int ptym_open(char *pts_name, int pts_namesz)
{
char *ptr;
int fdm, err;
if ((fdm = posix_openpt(O_RDWR)) < 0) {
assert(0);
return -1;
}
if (grantpt(fdm) < 0) {
assert(0);
return -1;
}
if (unlockpt(fdm) < 0) {
assert(0);
return -1;
}
if ((ptr = ptsname(fdm)) == NULL) {
assert(0);
return -1;
}
strncpy(pts_name, ptr, pts_namesz);
pts_name[pts_namesz - 1] = 0;
printf("pts_name:%s\n", pts_name);
return fdm;
}
int ptys_open(char *pts_name)
{
int fds;
if ((fds = open(pts_name, O_RDWR)) < 0) {
return -1;
}
return fds;
}
int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz)
{
int fdm, fds;
pid_t pid;
char pts_name[1024];
if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0) {
assert(0);
return -1;
}
if (slave_name != NULL) {
strncpy(slave_name, pts_name, slave_namesz);
slave_name[slave_namesz - 1] = 0;
}
if ((pid = fork()) < 0) {
assert(0);
return -1;
} else if (pid == 0) {
if (setsid() < 0) {
assert(0);
}
if ((fds = ptys_open(pts_name)) < 0) {
assert(0);
}
close(fdm);
if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) {
assert(0);
}
//if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) {
// assert(0);
//}
//if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) {
// assert(0);
//}
if ((fds != STDIN_FILENO) && (fds != STDOUT_FILENO) && (fds != STDERR_FILENO)) {
close(fds);
}
return 0;
} else {
*ptrfdm = fdm;
return pid;
}
}
int loop(int ptym)
{
pid_t pid;
int nread;
#define BUFFSIZE 512
char buf[BUFFSIZE];
if ((pid = fork()) < 0) {
assert(0);
} else if (pid == 0) {
while (1) {
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
} else if (nread = 0) {
break;
}
if (write(ptym, buf, nread) != nread) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
}
fsync(ptym);
}
exit(0); // child
}
while (1) {
if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) {
printf("%d break read\n", getpid());
break;
}
if (write(STDOUT_FILENO, buf, nread) != nread) {
assert(0);
}
}
}
int main(void)
{
int fdm;
char slave_name[1024];
pid_t pid = pty_fork(&fdm, slave_name, sizeof(slave_name));
if (pid < 0) {
assert(0);
} else if (pid == 0) {
int nread;
char buf[1024];
while(1){
if ((nread = read(STDIN_FILENO, buf, 3)) < 0) {
break;
}
printf("buf:%s\n", buf);
}
} else {
printf("child:%d#%s\n", pid, slave_name);
loop(fdm);
}
return 0;
}
Besides opening the pseudo-terminal, you have to initialize it (something referred to as line discipline). I don't see any of that in your example. You could compare with luit, which does do this (look for instance at the openTty function in sys.c).
Further reading:
Notes 7: Terminal I/O
Writing a Kernel Line Discipline
What are the responsibilities of each Pseudo-Terminal (PTY) component (software, master side, slave side)?

Resources