From 190fb06a3aaade80f7491a43fc6722a1689292d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Sat, 10 May 1997 05:57:39 -0700 Subject: [PATCH] fork() now returns an object thread_id->wait() implemented Rev: lib/master.pike:1.43.2.1 Rev: lib/modules/Process.pmod:1.7.2.1 Rev: src/backend.c:1.10.2.1 Rev: src/backend.h:1.2.2.1 Rev: src/configure.in:1.93.2.1 Rev: src/language.yacc:1.42.2.1 Rev: src/mapping.c:1.18.2.1 Rev: src/modules/files/efuns.c:1.22.2.1 Rev: src/modules/files/file.c:1.37.2.1 Rev: src/modules/files/socktest.pike:1.2.2.1 Rev: src/modules/readline/readlinemod.c:1.2.2.1 Rev: src/object.c:1.17.2.1 Rev: src/object.h:1.9.2.1 Rev: src/program.c:1.33.2.1 Rev: src/program.h:1.14.2.1 Rev: src/signal_handler.c:1.11.2.1 Rev: src/threads.c:1.23.2.1 --- lib/master.pike | 20 +++ lib/modules/Process.pmod | 37 +--- src/backend.c | 50 ++++-- src/backend.h | 3 + src/configure.in | 4 +- src/language.yacc | 66 ++++++-- src/mapping.c | 11 +- src/modules/files/efuns.c | 13 -- src/modules/files/file.c | 4 +- src/modules/files/socktest.pike | 4 +- src/modules/readline/readlinemod.c | 10 ++ src/object.c | 4 +- src/object.h | 3 + src/program.c | 47 +++++- src/program.h | 8 +- src/signal_handler.c | 263 ++++++++++++++++++++++++++--- src/threads.c | 73 +++++++- 17 files changed, 497 insertions(+), 123 deletions(-) diff --git a/lib/master.pike b/lib/master.pike index c56406f582..5aad3438d4 100644 --- a/lib/master.pike +++ b/lib/master.pike @@ -9,6 +9,8 @@ string *pike_include_path=({}); string *pike_module_path=({}); string *pike_program_path=({}); +int want_warnings; + mapping (string:string) environment=([]); varargs mixed getenv(string s) @@ -362,6 +364,7 @@ void _main(string *argv, string *env) q=tmp->find_all_options(argv,({ ({"version",tmp->NO_ARG,({"-v","--version"})}), ({"help",tmp->NO_ARG,({"-h","--help"})}), + ({"warnings",tmp->NO_ARG,({"-w","--warnings"})}), ({"execute",tmp->HAS_ARG,({"-e","--execute"})}), ({"modpath",tmp->HAS_ARG,({"-M","--module-path"})}), ({"ipath",tmp->HAS_ARG,({"-I","--include-path"})}), @@ -392,6 +395,10 @@ void _main(string *argv, string *env) { switch(opts[0]) { + case "warnings": + want_warnings++; + break; + case "version": werror(version() + " Copyright (C) 1994-1997 Fredrik H�binette\n" "Pike comes with ABSOLUTELY NO WARRANTY; This is free software and you are\n" @@ -497,6 +504,19 @@ void compile_error(string file,int line,string err) } } +void compile_warning(string file,int line,string err) +{ + if(!inhibit_compile_errors) + { + if(want_warnings) + werror(sprintf("%s:%d:%s\n",trim_file_name(file),line,err)); + } + else if(functionp(inhibit_compile_errors)) + { + inhibit_compile_errors(file,line,err); + } +} + /* This function is called whenever an #include directive is encountered * it receives the argument for #include and should return the file name * of the file to include diff --git a/lib/modules/Process.pmod b/lib/modules/Process.pmod index 7b7e61294b..18759713dd 100644 --- a/lib/modules/Process.pmod +++ b/lib/modules/Process.pmod @@ -19,18 +19,11 @@ varargs int exec(string file,string ... foo) return 69; } -varargs int spawn(string s,object stdin,object stdout,object stderr) +varargs object spawn(string s,object stdin,object stdout,object stderr) { - int pid; - - pid=fork(); - - if(pid==-1) - error("No more processes.\n"); - - if(pid) + if(object proc=fork()) { - return pid; + return proc; }else{ if(stdin) { stdin->dup2(File("stdin")); @@ -63,7 +56,7 @@ string popen(string s) p->close(); destruct(p); - t=read(0x7fffffff); + t=read(); if(!t) { int e; @@ -76,27 +69,7 @@ string popen(string s) return t; } -void system(string s) -{ - object p; - int pid; - string t; - - p=file::pipe(); - if(!p) error("System() failed.\n"); - p->set_close_on_exec(0); - if(pid=fork()) - { - destruct(p); - /* Nothing will ever be written here, we are just waiting for it - * to close - */ - file::read(1); - }else{ - exec("/bin/sh","-c",s); - exit(69); - } -} +int system(string s) { return spawn(s)->wait(); } constant fork = predef::fork; constant exece = predef::exece; diff --git a/src/backend.c b/src/backend.c index c73a46fcd3..588f28bde2 100644 --- a/src/backend.c +++ b/src/backend.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: backend.c,v 1.10 1997/03/01 01:43:01 hubbe Exp $"); +RCSID("$Id: backend.c,v 1.10.2.1 1997/05/10 12:56:54 hubbe Exp $"); #include "backend.h" #include <errno.h> #ifdef HAVE_SYS_TYPES_H @@ -72,6 +72,28 @@ void wake_up_backend(void) write(wakeup_pipe[1], &foo ,1); } +void init_signal_wait() +{ + may_need_wakeup=1; +} + +void exit_signal_wait() +{ + may_need_wakeup=0; +} + +void wait_for_signal() +{ + fd_set rset; + may_need_wakeup=1; + FD_ZERO(&rset); + FD_SET(wakeup_pipe[0], &rset); + THREADS_ALLOW(); + select(wakeup_pipe[0]+1, &rset, 0, 0, 0); + THREADS_DISALLOW(); + wakeup_callback(wakeup_pipe[0], 0); +} + void init_backend() { FD_ZERO(&selectors.read); @@ -221,21 +243,21 @@ void backend() next_timeout.tv_usec = 0; next_timeout.tv_sec = 7 * 24 * 60 * 60; /* See you in a week */ my_add_timeval(&next_timeout, ¤t_time); - + may_need_wakeup=1; call_callback(& backend_callbacks, (void *)0); - + check_threads_etc(); - - sets=selectors; - alloca(0); /* Do garbage collect */ + + sets=selectors; + #ifdef DEBUG if(d_flag > 1) do_debug(); #endif - + GETTIMEOFDAY(¤t_time); - + if(my_timercmp(&next_timeout, > , ¤t_time)) { my_subtract_timeval(&next_timeout, ¤t_time); @@ -243,20 +265,20 @@ void backend() next_timeout.tv_usec = 0; next_timeout.tv_sec = 0; } - + THREADS_ALLOW(); i=select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout); GETTIMEOFDAY(¤t_time); THREADS_DISALLOW(); may_need_wakeup=0; - + if(i>=0) { for(i=0; i<max_fd+1; i++) { if(FD_ISSET(i, &sets.read) && read_callback[i]) (*(read_callback[i]))(i,read_callback_data[i]); - + if(FD_ISSET(i, &sets.write) && write_callback[i]) (*(write_callback[i]))(i,write_callback_data[i]); } @@ -266,10 +288,10 @@ void backend() case EINVAL: fatal("Invalid timeout to select().\n"); break; - + case EINTR: /* ignore */ break; - + case EBADF: sets=selectors; next_timeout.tv_usec=0; @@ -279,7 +301,7 @@ void backend() fatal("Bad filedescriptor to select().\n"); } break; - + } } call_callback(& backend_callbacks, (void *)1); diff --git a/src/backend.h b/src/backend.h index f571718588..464c45b916 100644 --- a/src/backend.h +++ b/src/backend.h @@ -20,6 +20,9 @@ struct callback *add_backend_callback(callback_func call, void *arg, callback_func free_func); void wake_up_backend(void); +void init_signal_wait(); +void exit_signal_wait(); +void wait_for_signal(); void init_backend(); void set_read_callback(int fd,file_callback cb,void *data); void set_write_callback(int fd,file_callback cb,void *data); diff --git a/src/configure.in b/src/configure.in index c56aee0cbc..5026e7077f 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.93 1997/05/07 06:27:30 per Exp $") +AC_REVISION("$Id: configure.in,v 1.93.2.1 1997/05/10 12:56:54 hubbe Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -679,6 +679,8 @@ AC_CHECK_FUNCS( strtod \ strtok \ strtol \ + sigprocmask \ + sigblock \ times \ vfprintf \ vsprintf \ diff --git a/src/language.yacc b/src/language.yacc index 74aab449be..cf53c114e4 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -156,7 +156,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.42 1997/05/07 06:25:35 per Exp $"); +RCSID("$Id: language.yacc,v 1.42.2.1 1997/05/10 12:56:55 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -205,6 +205,17 @@ void fix_comp_stack(int sp) } } +void pop_local_variables(int level) +{ + while(local_variables->current_number_of_locals > level) + { + int e; + e=--(local_variables->current_number_of_locals); + free_string(local_variables->variable[e].name); + free_string(local_variables->variable[e].type); + } +} + %} %union @@ -795,13 +806,7 @@ block:'{' } statements '}' { - while(local_variables->current_number_of_locals > $<number>2) - { - int e; - e=--(local_variables->current_number_of_locals); - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); - } + pop_local_variables($<number>2); $$=$3; } ; @@ -932,12 +937,17 @@ class: modifiers F_CLASS optional_identifier } ; -cond: F_IF '(' comma_expr ')' statement optional_else_part +cond: F_IF + { + $<number>$=local_variables->current_number_of_locals; + } + '(' comma_expr ')' statement optional_else_part { - $$=mknode('?',$3,mknode(':',$5,$6)); + $$=mknode('?',$4,mknode(':',$6,$7)); $$->line_number=$1; $$=mkcastnode(void_type_string,$$); $$->line_number=$1; + pop_local_variables($<number>2); } ; @@ -945,10 +955,15 @@ optional_else_part: { $$=0; } | F_ELSE statement { $$=$2; } ; -foreach: F_FOREACH '(' expr0 ',' lvalue ')' statement +foreach: F_FOREACH { - $$=mknode(F_FOREACH,mknode(F_VAL_LVAL,$3,$5),$7); + $<number>$=local_variables->current_number_of_locals; + } + '(' expr0 ',' lvalue ')' statement + { + $$=mknode(F_FOREACH, mknode(F_VAL_LVAL,$4,$6),$8); $$->line_number=$1; + pop_local_variables($<number>2); } ; @@ -959,22 +974,32 @@ do: F_DO statement F_WHILE '(' comma_expr ')' ';' } ; -for: F_FOR '(' unused ';' for_expr ';' unused ')' statement +for: F_FOR + { + $<number>$=local_variables->current_number_of_locals; + } + '(' unused ';' for_expr ';' unused ')' statement { int i=current_line; current_line=$1; - $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$3),mknode(F_FOR,$5,mknode(':',$9,$7))); + $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$4),mknode(F_FOR,$6,mknode(':',$10,$8))); current_line=i; + pop_local_variables($<number>2); } ; -while: F_WHILE '(' comma_expr ')' statement +while: F_WHILE + { + $<number>$=local_variables->current_number_of_locals; + } + '(' comma_expr ')' statement { int i=current_line; current_line=$1; - $$=mknode(F_FOR,$3,mknode(':',$5,NULL)); + $$=mknode(F_FOR,$4,mknode(':',$6,NULL)); current_line=i; + pop_local_variables($<number>2); } ; @@ -982,10 +1007,15 @@ for_expr: /* EMPTY */ { $$=mkintnode(1); } | comma_expr ; -switch: F_SWITCH '(' comma_expr ')' statement +switch: F_SWITCH + { + $<number>$=local_variables->current_number_of_locals; + } + '(' comma_expr ')' statement { - $$=mknode(F_SWITCH,$3,$5); + $$=mknode(F_SWITCH,$4,$6); $$->line_number=$1; + pop_local_variables($<number>2); } ; diff --git a/src/mapping.c b/src/mapping.c index 82a95a0f3f..80ae947486 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mapping.c,v 1.18 1997/04/23 23:06:16 hubbe Exp $"); +RCSID("$Id: mapping.c,v 1.18.2.1 1997/05/10 12:56:55 hubbe Exp $"); #include "main.h" #include "types.h" #include "object.h" @@ -495,6 +495,15 @@ struct svalue *low_mapping_string_lookup(struct mapping *m, return low_mapping_lookup(m, &tmp); } +struct svalue *low_mapping_int_lookup(struct mapping *m, + INT32 p) +{ + struct svalue tmp; + tmp.type=T_INT; + tmp.u.integer=p; + return low_mapping_lookup(m, &tmp); +} + void mapping_index_no_free(struct svalue *dest, struct mapping *m, struct svalue *key) diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c index a0b34014d3..b190fd0c97 100644 --- a/src/modules/files/efuns.c +++ b/src/modules/files/efuns.c @@ -357,18 +357,6 @@ void f_getcwd(INT32 args) free(e); } -void f_fork(INT32 args) -{ - do_set_close_on_exec(); - pop_n_elems(args); -#if defined(HAVE_FORK1) && defined(_REENTRANT) - push_int(fork1()); -#else - push_int(fork()); -#endif -} - - void f_exece(INT32 args) { INT32 e; @@ -526,7 +514,6 @@ void init_files_efuns() add_efun("get_dir",f_get_dir,"function(string:string *)",OPT_EXTERNAL_DEPEND); add_efun("cd",f_cd,"function(string:int)",OPT_SIDE_EFFECT); add_efun("getcwd",f_getcwd,"function(:string)",OPT_EXTERNAL_DEPEND); - add_efun("fork",f_fork,"function(:int)",OPT_SIDE_EFFECT); add_efun("exece",f_exece,"function(string,mixed*,void|mapping(string:string):int)",OPT_SIDE_EFFECT); #ifdef HAVE_STRERROR diff --git a/src/modules/files/file.c b/src/modules/files/file.c index c1cba2ced7..a31053a664 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -6,7 +6,7 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.37 1997/05/05 05:29:37 nisse Exp $"); +RCSID("$Id: file.c,v 1.37.2.1 1997/05/10 12:57:28 hubbe Exp $"); #include "types.h" #include "interpret.h" #include "svalue.h" @@ -1465,7 +1465,7 @@ void pike_module_init() add_function("open",file_open,"function(string,string:int)",0); add_function("close",file_close,"function(string|void:int)",0); - add_function("read",file_read,"function(int,int|void:int|string)",0); + add_function("read",file_read,"function(int|void,int|void:int|string)",0); add_function("write",file_write,"function(string:int)",0); add_function("seek",file_seek,"function(int:int)",0); diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike index 6952a7caa0..354457746b 100755 --- a/src/modules/files/socktest.pike +++ b/src/modules/files/socktest.pike @@ -232,7 +232,7 @@ void finish() case 22: werror("Testing accept. "); string data1=strmult("foobar",4711); - for(e=0;e<10;e++) + for(int e=0;e<10;e++) { sock1=Socket(); sock1->connect("127.0.0.1",portno1); @@ -243,7 +243,7 @@ void finish() case 23..45: tests=(_tests-22)*2; werror("Testing "+(tests*2)+" sockets. "); - for(e=0;e<tests;e++) stdtest(); + for(int e=0;e<tests;e++) stdtest(); break; case 46: diff --git a/src/modules/readline/readlinemod.c b/src/modules/readline/readlinemod.c index 6aa2001375..35e07b41f1 100644 --- a/src/modules/readline/readlinemod.c +++ b/src/modules/readline/readlinemod.c @@ -59,10 +59,20 @@ static void f_readline(INT32 args) error("Bad argument 1 to readline()\n"); str=sp[-args].u.string; +retry: THREADS_ALLOW(); r=readline(str->str); THREADS_DISALLOW(); +#ifdef _REENTRANT + /* This kluge might fix some problems with readline and threads */ + if(!r && errno==EINTR) + { + check_threads_etc(); + goto retry; + } +#endif + pop_n_elems(args); if(r) { diff --git a/src/object.c b/src/object.c index 93cd6cac8c..af163ae754 100644 --- a/src/object.c +++ b/src/object.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: object.c,v 1.17 1997/04/16 03:09:14 hubbe Exp $"); +RCSID("$Id: object.c,v 1.17.2.1 1997/05/10 12:56:56 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -416,7 +416,7 @@ void object_index_no_free(struct svalue *to, } -static void object_low_set_index(struct object *o, +void object_low_set_index(struct object *o, int f, struct svalue *from) { diff --git a/src/object.h b/src/object.h index 28f4d91878..5ac6bae012 100644 --- a/src/object.h +++ b/src/object.h @@ -54,6 +54,9 @@ void object_index_no_free2(struct svalue *to, void object_index_no_free(struct svalue *to, struct object *o, struct svalue *index); +void object_low_set_index(struct object *o, + int f, + struct svalue *from); void object_set_index2(struct object *o, struct svalue *index, struct svalue *from); diff --git a/src/program.c b/src/program.c index c1020557eb..edb83e8c18 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.33 1997/04/16 03:09:16 hubbe Exp $"); +RCSID("$Id: program.c,v 1.33.2.1 1997/05/10 12:56:56 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -28,6 +28,11 @@ RCSID("$Id: program.c,v 1.33 1997/04/16 03:09:16 hubbe Exp $"); #include <errno.h> #include <fcntl.h> + +#undef ATTRIBUTE +#define ATTRIBUTE(X) + + /* * Define the size of the cache that is used for method lookup. */ @@ -962,6 +967,21 @@ int define_variable(struct pike_string *name, return n; } +int simple_add_variable(char *name, + char *type, + INT32 flags) +{ + INT32 ret; + struct pike_string *name_s, *type_s; + name_s=make_shared_string(name); + type_s=parse_type(type); + + ret=define_variable(name_s, type_s, flags); + free_string(name_s); + free_string(type_s); + return ret; +} + int add_constant(struct pike_string *name, struct svalue *c, INT32 flags) @@ -1455,10 +1475,10 @@ char *get_line(unsigned char *pc,struct program *prog,INT32 *linep) return file; } -void my_yyerror(char *fmt,...) +void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))) { va_list args; - char buf[1000]; + char buf[8192]; va_start(args,fmt); VSPRINTF(buf,fmt,args); @@ -1756,3 +1776,24 @@ char *get_storage(struct object *o, struct program *p) if(offset == -1) return 0; return o->storage + offset; } + +void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))) +{ + char buf[4711]; + va_list args; + va_start(args,fmt); + VSPRINTF(buf, fmt, args); + va_end(args); + + if(strlen(buf)>sizeof(buf)) + fatal("Buffer overfloat in yywarning!\n"); + + if(get_master()) + { + ref_push_string(current_file); + push_int(current_line); + push_text(buf); + SAFE_APPLY_MASTER("compile_warning",3); + pop_stack(); + } +} diff --git a/src/program.h b/src/program.h index 900c03156d..6444becb75 100644 --- a/src/program.h +++ b/src/program.h @@ -202,6 +202,9 @@ int isidentifier(struct pike_string *s); int define_variable(struct pike_string *name, struct pike_string *type, INT32 flags); +int simple_add_variable(char *name, + char *type, + INT32 flags); int add_constant(struct pike_string *name, struct svalue *c, INT32 flags); @@ -236,7 +239,7 @@ int store_constant(struct svalue *foo, int equal); void start_line_numbering(void); void store_linenumber(INT32 current_line, struct pike_string *current_file); char *get_line(unsigned char *pc,struct program *prog,INT32 *linep); -void my_yyerror(char *fmt,...); +void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))); void compile(); struct program *compile_file(struct pike_string *file_name); struct program *compile_string(struct pike_string *prog, @@ -252,11 +255,10 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_); void push_locals(); void pop_locals(); char *get_storage(struct object *o, struct program *p); +void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))); /* Prototypes end here */ -void my_yyerror(char *fmt,...) ATTRIBUTE((format (printf, 1, 2))); - #endif diff --git a/src/signal_handler.c b/src/signal_handler.c index dbcf0020d3..11072365f1 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -12,6 +12,8 @@ #include "backend.h" #include "error.h" #include "callback.h" +#include "mapping.h" +#include "object.h" #include <signal.h> #include <sys/wait.h> @@ -32,6 +34,7 @@ static struct svalue signal_callbacks[MAX_SIGNALS]; static unsigned char sigbuf[SIGNAL_BUFFER]; static int firstsig, lastsig; static struct callback *signal_evaluator_callback =0; +static int sigchild_arrived=0; struct sigdesc @@ -192,30 +195,6 @@ static void my_signal(int sig, sigfunctype fun) #endif } -static RETSIGTYPE sig_child(int arg) -{ - /* We carefully reap what we saw */ -#ifdef HAVE_WAITPID - while(waitpid(-1,0,WNOHANG) > 0); -#else -#ifdef HAVE_WAIT3 - while( wait3(0,WNOHANG,0) > 0); -#else -#ifdef HAVE_WAIT4 - while( wait4(-1,0,WNOHANG,0) > 0); -#else - - /* Leave'em hanging */ - -#endif /* HAVE_WAIT4 */ -#endif /* HAVE_WAIT3 */ -#endif /* HAVE_WAITPID */ - -#ifdef SIGNAL_ONESHOT - my_signal(SIGCHLD, sig_child); -#endif -} - static RETSIGTYPE receive_signal(int signum) { int tmp; @@ -225,7 +204,8 @@ static RETSIGTYPE receive_signal(int signum) if(tmp != lastsig) sigbuf[firstsig=tmp]=signum; - if(signum==SIGCHLD) sig_child(signum); + if(signum==SIGCHLD) + sigchild_arrived++; wake_up_backend(); @@ -268,6 +248,193 @@ void check_signals(struct callback *foo, void *bar, void *gazonk) } } +#define PROCESS_UNKNOWN 0 +#define PROCESS_RUNNING 1 +#define PROCESS_EXITED 2 + +#define THIS ((struct pid_status *)fp->current_storage) + +static struct callback *children_evaluator_callback =0; +struct mapping *pid_mapping=0;; +struct program *pid_status_program=0; + +struct pid_status +{ + int pid; + int state; + int result; +}; + +static void init_pid_status(struct object *o) +{ + THIS->pid=-1; + THIS->state=PROCESS_UNKNOWN; + THIS->result=-1; +} + +static void exit_pid_status(struct object *o) +{ + if(pid_mapping) + { + struct svalue key; + key.type=T_INT; + key.u.integer=THIS->pid; + map_delete(pid_mapping, &key); + } +} + +static RETSIGTYPE sig_child(int arg) +{ + wake_up_backend(); + fprintf(stderr,"Got sigchild %d\n",sigchild_arrived); + sigchild_arrived++; + +#ifdef SIGNAL_ONESHOT + my_signal(SIGCHLD, sig_child); +#endif +} + +static void check_children(struct callback *foo, void *bar, void *gazonk) +{ + if(sigchild_arrived) + { +#ifdef HAVE_SIGPROCMASK + sigset_t set, oset; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, &oset); +#else +#ifdef HAVE_SIGBLOCK + int oset; + oset=siggetmask(); + sigblock(sigmask(SIGCHLD)); +#endif +#endif + while(sigchild_arrived>0) + { + sigchild_arrived--; + while(1) + { + pid_t pid; + int status; + fprintf(stderr,"Waitpid...\n"); + /* We carefully reap what we saw */ +#ifdef HAVE_WAITPID + pid=waitpid(-1,& status,WNOHANG); +#else +#ifdef HAVE_WAIT3 + pid=wait3(&status,WNOHANG,0); +#else +#ifdef HAVE_WAIT4 + pid=wait4(-1,&status,WNOHANG,0); +#else + pid=-1; +#endif +#endif +#endif + fprintf(stderr,"Done...\n"); + if(pid>0) + { + if(pid_mapping) + { + struct svalue *s, key; + key.type=T_INT; + key.u.integer=pid; + if((s=low_mapping_lookup(pid_mapping, &key))) + { + if(s->type == T_OBJECT) + { + struct pid_status *p; + if((p=(struct pid_status *)get_storage(s->u.object, + pid_status_program))) + { + p->state = PROCESS_EXITED; + p->result = WEXITSTATUS(status); + } + } + map_delete(pid_mapping, &key); + } + } + }else{ + break; + } + } + } + +#ifdef HAVE_SIGPROCMASK + sigprocmask(SIG_SETMASK, &oset, 0); +#else +#ifdef HAVE_SIGBLOCk + sigsetmask(oset); +#endif +#endif + } +} + +static void f_pid_status_wait(INT32 args) +{ + pop_n_elems(args); + init_signal_wait(); + printf("Init wait\n"); + while(THIS->state == PROCESS_RUNNING) + { + printf("Waiting...\n"); + wait_for_signal(); + printf("Woke up! %d\n",sigchild_arrived); + check_threads_etc(); + } + printf("Done!\n"); + exit_signal_wait(); + push_int(THIS->result); +} + +static void f_pid_status_status(INT32 args) +{ + pop_n_elems(args); + push_int(THIS->state); +} + +static void f_pid_status_pid(INT32 args) +{ + pop_n_elems(args); + push_int(THIS->pid); +} + +void f_fork(INT32 args) +{ + struct object *o; + pid_t pid; + pop_n_elems(args); +#if defined(HAVE_FORK1) && defined(_REENTRANT) + pid=fork1(); +#else + pid=fork(); +#endif + if(pid==-1) error("Fork failed\n"); + + if(pid) + { + struct pid_status *p; + if(!children_evaluator_callback) + { + children_evaluator_callback=add_to_callback(&evaluator_callbacks, + check_children, + 0,0); + } + o=clone_object(pid_status_program,0); + p=(struct pid_status *)get_storage(o,pid_status_program); + p->pid=pid; + p->state=PROCESS_RUNNING; + push_object(o); + push_int(pid); + mapping_insert(pid_mapping,sp-1, sp-2); + pop_stack(); + }else{ + push_int(0); + } +} + + /* Get the name of a signal given the number */ static char *signame(int sig) { @@ -385,10 +552,30 @@ static void f_signame(int args) static void f_kill(INT32 args) { + pid_t pid; if(args < 2) error("Too few arguments to kill().\n"); - if(sp[-args].type != T_INT) + switch(sp[-args].type) + { + case T_INT: + pid=sp[-args].u.integer; + break; + + case T_OBJECT: + { + struct pid_status *p; + if((p=(struct pid_status *)get_storage(sp[-args].u.object, + pid_status_program))) + { + pid=p->pid; + break; + } + } + default: error("Bad argument 1 to kill().\n"); + } + + if(sp[-args].type != T_INT) if(sp[1-args].type != T_INT) error("Bad argument 1 to kill().\n"); @@ -452,12 +639,23 @@ void init_signals() firstsig=lastsig=0; + pid_mapping=allocate_mapping(2); + start_new_program(); + add_storage(sizeof(struct pid_status)); + set_init_callback(init_pid_status); + set_init_callback(exit_pid_status); + add_function("wait",f_pid_status_wait,"function(:int)",0); + add_function("status",f_pid_status_status,"function(:int)",0); + add_function("pid",f_pid_status_pid,"function(:int)",0); + pid_status_program=end_program(); + add_efun("signal",f_signal,"function(int,mixed|void:void)",OPT_SIDE_EFFECT); - add_efun("kill",f_kill,"function(int,int:int)",OPT_SIDE_EFFECT); + add_efun("kill",f_kill,"function(int|object,int:int)",OPT_SIDE_EFFECT); add_efun("signame",f_signame,"function(int:string)",0); add_efun("signum",f_signum,"function(string:int)",0); add_efun("getpid",f_getpid,"function(:int)",0); add_efun("alarm",f_alarm,"function(int:int)",OPT_SIDE_EFFECT); + add_efun("fork",f_fork,"function(:object)",OPT_SIDE_EFFECT); #ifdef HAVE_UALARM add_efun("ualarm",f_ualarm,"function(int:int)",OPT_SIDE_EFFECT); #endif @@ -466,6 +664,17 @@ void init_signals() void exit_signals() { int e; + if(pid_mapping) + { + free_mapping(pid_mapping); + pid_mapping=0; + } + + if(pid_status_program) + { + free_program(pid_status_program); + pid_status_program=0; + } for(e=0;e<MAX_SIGNALS;e++) { free_svalue(signal_callbacks+e); diff --git a/src/threads.c b/src/threads.c index b87be89dc3..0f1af7aa4d 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.23 1997/04/20 03:53:35 grubba Exp $"); +RCSID("$Id: threads.c,v 1.23.2.1 1997/05/10 12:56:57 hubbe Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -30,6 +30,19 @@ struct thread_starter struct array *args; }; +struct thread_id { + int status; + COND_T status_change; +}; + +static int thread_id_result_variable; + +static MUTEX_T thread_id_kluge = PTHREAD_MUTEX_INITIALIZER; + +#define THREAD_UNKNOWN 0 +#define THREAD_RUNNING 1 +#define THREAD_EXITED 2 + static void check_threads(struct callback *cb, void *arg, void * arg2) { THREADS_ALLOW(); @@ -39,6 +52,42 @@ static void check_threads(struct callback *cb, void *arg, void * arg2) THREADS_DISALLOW(); } +#define THIS_THREAD ((struct thread_id *)fp->current_storage) +#define THREAD_INFO ((struct thread_id *)thread_id->storage) + +static void init_thread_id(struct object *o) +{ + THIS_THREAD->status=THREAD_UNKNOWN; + co_init(& THIS_THREAD->status_change); +} + +static void exit_thread_id(struct object *o) +{ + co_destroy(& THIS_THREAD->status_change); +} + +static void f_thread_id_status(INT32 args) +{ + pop_n_elems(args); + push_int(THIS_THREAD->status); +} + +static void f_thread_id_result(INT32 args) +{ + struct thread_id *th=THIS_THREAD; + THREADS_ALLOW(); + mt_lock(&thread_id_kluge); + while(th->status != THREAD_EXITED) + co_wait(&th->status_change, &thread_id_kluge); + mt_unlock(&thread_id_kluge); + THREADS_DISALLOW(); + + low_object_index_no_free(sp, + fp->current_object, + thread_id_result_variable); + sp++; +} + void *new_thread_func(void * data) { /* static int dbt;*/ @@ -54,6 +103,7 @@ void *new_thread_func(void * data) init_interpreter(); thread_id=arg.id; + THREAD_INFO->status=THREAD_RUNNING; if(SETJMP(back)) { @@ -68,12 +118,19 @@ void *new_thread_func(void * data) push_array_items(arg.args); arg.args=0; f_call_function(args); - pop_stack(); /* Discard the return value. /Per */ + + fprintf(stderr,"Done "); + /* copy return value to the thread_id here */ + object_low_set_index(thread_id, + thread_id_result_variable, + sp-1); + pop_stack(); } UNSETJMP(back); - destruct(thread_id); + THREAD_INFO->status=THREAD_EXITED; + co_signal(& THREAD_INFO->status_change); free_object(thread_id); thread_id=0; @@ -104,6 +161,7 @@ void f_thread_create(INT32 args) arg=ALLOC_STRUCT(thread_starter); arg->args=aggregate_array(args); arg->id=clone_object(thread_id_prog,0); + arg->id->refs++; tmp=th_create(&dummy,new_thread_func,arg); @@ -121,8 +179,8 @@ void f_thread_create(INT32 args) th_setconcurrency(++num_lwps); #endif push_object(arg->id); - arg->id->refs++; } else { + free_object(arg->id); free_object(arg->id); free_array(arg->args); free((char *)arg); @@ -365,6 +423,12 @@ void th_init() end_class("condition", 0); start_new_program(); + add_storage(sizeof(struct thread_id)); + thread_id_result_variable=simple_add_variable("result","mixed",0); + add_function("wait",f_thread_id_result,"function(:int)",0); + add_function("status",f_thread_id_status,"function(:int)",0); + set_init_callback(init_thread_id); + set_exit_callback(exit_thread_id); thread_id_prog=end_program(); if(!mutex_key) fatal("Failed to initialize thread program!\n"); @@ -388,7 +452,6 @@ void th_cleanup() if(thread_id) { - destruct(thread_id); free_object(thread_id); thread_id=0; } -- GitLab