halayli/lthread

Assertion failed: (lt_write != NULL || lt_read != NULL), function lthread_run, file lthread_sched.c, line 252.

Opened this issue · 2 comments

To run an lthread scheduler in each pthread, launch a pthread and create lthreads using lthread_create() followed by lthread_run() in each pthread.

when create more then one pthread and lthread scheduler,and use "ab -c 100 -n 10000" to test program,then "Assertion failed: (lt_write != NULL || lt_read != NULL), function lthread_run, file lthread_sched.c, line 252." occure.

But only one pthread will run ok.

static
void* accept_loop(void* args)
{
lthread_t *lt = NULL;
lthread_create(&lt, listener, NULL);
lthread_run();
}

int
main(int argc, char **argv)
{
......

int num = 4;
int i = 0;
pthread_t ths[num];
while (i++ < num) {
	pthread_create(&ths[i], NULL, accept_loop, NULL);
}

i = 0;
while (i++ < num) {
	pthread_join(ths[i], NULL);
}

return 0;

}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <lthread.h>

struct cli_info {
/* other stuff if needed*/
struct sockaddr_in peer_addr;
int fd;
};

typedef struct cli_info cli_info_t;

char *reply = "HTTP/1.0 200 OK\r\nContent-length: 11\r\n\r\nHello Kannan";

int lsn_fd = 0;

void
http_serv(void *arg)
{
cli_info_t *cli_info = arg;
char *buf = NULL;
unsigned long long int ret = 0;
char ipstr[INET6_ADDRSTRLEN];
lthread_detach();

inet_ntop(AF_INET, &cli_info->peer_addr.sin_addr, ipstr, INET_ADDRSTRLEN);
printf("Accepted connection on IP %s\n", ipstr);

if ((buf = malloc(1024)) == NULL)
    return;

/* read data from client or timeout in 5 secs */
ret = lthread_recv(cli_info->fd, buf, 1024, 0, 5000);

/* did we timeout before the user has sent us anything? */
if (ret == -2) {
    lthread_close(cli_info->fd);
    free(buf);
    free(arg);
    return;
}

/* reply back to user */
lthread_send(cli_info->fd, reply, strlen(reply), 0);
lthread_close(cli_info->fd);
free(buf);
free(arg);
}

void
listener(lthread_t *lt, void *arg)
{
int cli_fd = 0;
int ret = 0;

struct sockaddr_in peer_addr = {};
socklen_t addrlen = sizeof(peer_addr);
lthread_t *cli_lt = NULL;
cli_info_t *cli_info = NULL;
char ipstr[INET6_ADDRSTRLEN];

DEFINE_LTHREAD;

while (1) {
    /* block until a new connection arrives */
    cli_fd = lthread_accept(lsn_fd, (struct sockaddr*)&peer_addr, &addrlen);
    if (cli_fd == -1) {
        perror("Failed to accept connection");
        return;
    }

    if ((cli_info = malloc(sizeof(cli_info_t))) == NULL) {
        close(cli_fd);
        continue;
    }
    cli_info->peer_addr = peer_addr;
    cli_info->fd = cli_fd;
    /* launch a new lthread that takes care of this client */
    ret = lthread_create(&cli_lt, http_serv, cli_info);
}

}

static
void* accept_loop(void* args)
{
lthread_t *lt = NULL;
lthread_create(&lt, listener, NULL);
lthread_run();
}

int
main(int argc, char **argv)
{
int cli_fd = 0;
int opt = 1;
int ret = 0;
struct sockaddr_in sin = {};
lthread_t *cli_lt = NULL;
cli_info_t *cli_info = NULL;
char ipstr[INET6_ADDRSTRLEN];
lthread_t *lt = NULL;

/* create listening socket */
lsn_fd = lthread_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (lsn_fd == -1)
    return 0;

if (setsockopt(lsn_fd, SOL_SOCKET, SO_REUSEADDR, &opt,sizeof(int)) == -1)
    perror("failed to set SOREUSEADDR on socket");

sin.sin_family = PF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(3128);

/* bind to the listening port */
ret = bind(lsn_fd, (struct sockaddr *)&sin, sizeof(sin));
if (ret == -1) {
    perror("Failed to bind on port 3128");
    return 0;
}

printf("Starting listener on 3128\n");

listen(lsn_fd, 128);

int num = 4;
int i = 0;
pthread_t ths[num];
while (i++ < num) {
	pthread_create(&ths[i], NULL, accept_loop, NULL);
}

i = 0;
while (i++ < num) {
	pthread_join(ths[i], NULL);
}

return 0;

}