Hi,
If I use the modified version of client.c and test8.ok below in gambit/tests I get the following:
$ make check ...... 7d6 < Cleanup successful make: *** [test8] Error 1 $
If I keep the executable client from make check the following happens:
$ ./client result = #!void result = 1606938044258990275541962092341162602522202993782792835301376 result = #<datum-parsing-exception #2> result = #<unbound-global-exception #3> Starting cleanup...1 Starting cleanup...2 $
Should "Cleanup successful" (see client.c below) be printed after the call to __cleanup()? This might be causing the problem of calling __cleanup() from Python.
Thanks,
-Dave
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
** test8.ok:
result = #!void result = 1606938044258990275541962092341162602522202993782792835301376 result = #<datum-parsing-exception #2> result = #<unbound-global-exception #3> Starting cleanup...1 Starting cleanup...2 Cleanup successful
** client.c:
/* File: "client.c", Time-stamp: <2007-09-12 00:07:21 feeley> */
/* Copyright (c) 1996-2007 by Marc Feeley, All Rights Reserved. */
#include <stdio.h> #include <stdlib.h>
/* * ___VERSION must match the version number of the Gambit header file. */
#define ___VERSION 406000 #include "gambit.h"
/* * Include declarations exported by server. */
#include "server.h"
/* * Define SCHEME_LIBRARY_LINKER as the name of the Scheme library * prefixed with "____20_" and suffixed with "__". This is the * function that initializes the Scheme library. */
#define SCHEME_LIBRARY_LINKER ____20_server__
___BEGIN_C_LINKAGE extern ___mod_or_lnk SCHEME_LIBRARY_LINKER (___global_state_struct*); ___END_C_LINKAGE
int main (int argc, char **argv) { char *temp;
/* * Setup the Scheme library by calling "___setup" with appropriate * parameters. The call to "___setup_params_reset" sets all parameters * to their default setting. */
___setup_params_struct setup_params;
___setup_params_reset (&setup_params);
setup_params.version = ___VERSION; setup_params.linker = SCHEME_LIBRARY_LINKER;
___setup (&setup_params);
/* Main part of program: call Scheme functions */
temp = eval_string ("(define x 200)"); if (temp != 0) { printf ("result = %s\n", temp); ___release_string (temp); /* don't forget to reclaim string */ }
temp = eval_string ("(expt 2 x)"); if (temp != 0) { printf ("result = %s\n", temp); ___release_string (temp); }
temp = eval_string ("(+ 1 2"); /* note: missing closing parenthesis */ if (temp != 0) { printf ("result = %s\n", temp); ___release_string (temp); }
temp = eval_string ("(+ x y)"); /* note: y is unbound */ if (temp != 0) { printf ("result = %s\n", temp); ___release_string (temp); }
fflush (stdout);
/* Cleanup the Scheme library */
printf ("Starting cleanup...1\n"); fflush (stdout);
printf ("Starting cleanup...2\n"); fflush (stdout);
___cleanup ();
printf ("Cleanup successful\n"); fflush (stdout);
return 0; }
Afficher les réponses par date
It could be the call to ___release_foreign (in c_intf.c) that's causing the trouble. The calling sequence is:
___cleanup (setup.c) => ___cleanup_mem (mem.c) => free_still_objs (mem.c) => ___release_foreign (c_intf.c)
With this (modified) snippet from free_still_objs:
----------------------------------------------------------------------
if (release_fn != 0) { printf (" >>> ___release_foreign 3a\n"); fflush (stdout); ptr = ___CAST(void*,___FIELD(obj,___FOREIGN_PTR)); ___FIELD(obj,___FOREIGN_RELEASE_FN) = ___CAST(___SCMOBJ,___CAST(___SCMOBJ (*) ___P((void *ptr),()),0));
printf (" >>> ___release_foreign 3b\n"); fflush (stdout); ___FIELD(obj,___FOREIGN_PTR) = ___CAST(___SCMOBJ,___CAST(void*,0));
printf (" >>> ___release_foreign 3c\n"); fflush (stdout); printf (" >>> ___FIX(___NO_ERR) = %i\n" , ___FIX(___NO_ERR)); fflush (stdout); e = release_fn (ptr); printf (" >>> e = release_fn (ptr) : %i\n" , e); fflush (stdout); printf (" >>> ((e = release_fn (ptr)) != ___FIX(___NO_ERR)) = %i\n" , (e != ___FIX(___NO_ERR))); fflush (stdout); if (e != ___FIX(___NO_ERR)) { printf (" >>> ___release_foreign 3d\n"); printf (" >>> e = %d\n" , e); fflush (stdout); return e; } } ----------------------------------------------------------------------
I'll get, e.g., the following output to the terminal:
$ ./client ......
___release_foreign 3a ___release_foreign 3b ___release_foreign 3c ___FIX(___NO_ERR) = 0 e = release_fn (ptr) : 0 ((e = release_fn (ptr)) != ___FIX(___NO_ERR)) = 0
.....
___release_foreign 3a ___release_foreign 3b ___release_foreign 3c ___FIX(___NO_ERR) = 0
$
So maybe release_fn is the problem?
Commenting out the call to ___cleanup_mem in ___cleanup, the code still fails on ___cleanup_os. Here it seems to have something to do with ___device_group_cleanup in os_io.c. Now the call sequence is:
___cleanup (setup.c) => ___cleanup_os (os.c) => ___cleanup_io_module (os_io,c) => io_module_cleanup (os_io,c) => ___device_group_cleanup (os_io.c)
Here it seems to be a problem with the line:
if (___device_cleanup (dgroup->list) != ___FIX(___NO_ERR))
Here I'll get
___device_group_cleanup 2 ___device_group_cleanup 2d
(___device_cleanup (dgroup->list) : 0
___FIX(___NO_ERR) : 0 ___device_group_cleanup 2c
(___device_cleanup (dgroup->list) != ___FIX(___NO_ERR)) = 0
___device_group_cleanup 2b ___device_group_cleanup 2
with this modified snippet in ___device_group_cleanup (os_io.c):
----------------------------------------------------------------------
{ printf ("___device_group_cleanup 2\n"); fflush (stdout);
aa = ___device_cleanup (dgroup->list); printf ("___device_group_cleanup 2d\n"); fflush (stdout); bb = ___FIX(___NO_ERR);
printf (" >>> (___device_cleanup (dgroup->list) : %i\n" , aa); fflush(stdout); printf("___FIX(___NO_ERR) : %i\n",bb); fflush(stdout); printf ("___device_group_cleanup 2c\n"); fflush (stdout); printf (" >>> (___device_cleanup (dgroup->list) != ___FIX(___NO_ERR)) = %d\n" , (aa != bb)); fflush (stdout); if (aa != bb) { printf ("___device_group_cleanup 2a\n"); fflush (stdout); break; } printf ("___device_group_cleanup 2b\n"); fflush (stdout); }
----------------------------------------------------------------------
So maybe ___device_cleanup is causing a problem also?
Thanks again!
-Dave
On 2011-01-12, at 8:17 AM, David Dreisigmeyer wrote:
It could be the call to ___release_foreign (in c_intf.c) that's causing the trouble. The calling sequence is:
___cleanup (setup.c) => ___cleanup_mem (mem.c) => free_still_objs (mem.c) => ___release_foreign (c_intf.c)
With this (modified) snippet from free_still_objs:
As far as I know, in the unmodified Gambit, there are no foreign objects with release functions. So I don't understand why you get release_fn != NULL. So if you comment out the call to the release_fn, does the problem go away?
Commenting out the call to ___cleanup_mem in ___cleanup, the code still fails on ___cleanup_os. Here it seems to have something to do with ___device_group_cleanup in os_io.c. Now the call sequence is:
___cleanup (setup.c) => ___cleanup_os (os.c) => ___cleanup_io_module (os_io,c) => io_module_cleanup (os_io,c) => ___device_group_cleanup (os_io.c)
Here it seems to be a problem with the line:
if (___device_cleanup (dgroup->list) != ___FIX(___NO_ERR))
It would be interesting to know which device is failing to cleanup properly. My hunch is that Python is closing a file descriptor or changing an attribute of the file descriptor that Gambit expects to be in a particular state when it cleans up, so when it tries to close it (or call select on it), a failure is reported. The failure will happen in one of the ___device_XXX_close_raw_virt functions in lib/os_io.c or lib/os_tty.c (most probably in ___device_file_close_raw_virt or ___device_tty_close_raw_virt).
Marc
This wasn't used with Python. I started with modifying the client.c file included in gambit/tests and proceeded from there. I'll check on commenting out the call to release_fn soon.
Thanks Marc,
-Dave
On Wed, Jan 12, 2011 at 8:36 AM, Marc Feeley feeley@iro.umontreal.ca wrote:
On 2011-01-12, at 8:17 AM, David Dreisigmeyer wrote:
It could be the call to ___release_foreign (in c_intf.c) that's causing the trouble. The calling sequence is:
___cleanup (setup.c) => ___cleanup_mem (mem.c) => free_still_objs (mem.c) => ___release_foreign (c_intf.c)
With this (modified) snippet from free_still_objs:
As far as I know, in the unmodified Gambit, there are no foreign objects with release functions. So I don't understand why you get release_fn != NULL. So if you comment out the call to the release_fn, does the problem go away?
Commenting out the call to ___cleanup_mem in ___cleanup, the code still fails on ___cleanup_os. Here it seems to have something to do with ___device_group_cleanup in os_io.c. Now the call sequence is:
___cleanup (setup.c) => ___cleanup_os (os.c) => ___cleanup_io_module (os_io,c) => io_module_cleanup (os_io,c) => ___device_group_cleanup (os_io.c)
Here it seems to be a problem with the line:
if (___device_cleanup (dgroup->list) != ___FIX(___NO_ERR))
It would be interesting to know which device is failing to cleanup properly. My hunch is that Python is closing a file descriptor or changing an attribute of the file descriptor that Gambit expects to be in a particular state when it cleans up, so when it tries to close it (or call select on it), a failure is reported. The failure will happen in one of the ___device_XXX_close_raw_virt functions in lib/os_io.c or lib/os_tty.c (most probably in ___device_file_close_raw_virt or ___device_tty_close_raw_virt).
Marc
On 2011-01-12, at 8:44 AM, David Dreisigmeyer wrote:
This wasn't used with Python. I started with modifying the client.c file included in gambit/tests and proceeded from there. I'll check on commenting out the call to release_fn soon.
Thanks Marc,
-Dave
OK, I misunderstood. Now I think the problem is that Gambit is closing stdin/stdout/stderr in ___cleanup(), so when you do a printf after the call to ___cleanup, there is no output.
Please try this: in lib/os_io.c in function ___device_file_close_raw_virt, replace
#ifdef USE_POSIX if (close_no_EINTR (d->fd) < 0) return err_code_from_errno (); #endif
with
#ifdef USE_POSIX if (d->fd > 2 && close_no_EINTR (d->fd) < 0) return err_code_from_errno (); #endif
This will prevent closing stdin/stdout/stderr. If that fixes your problem, then I'll try to find a better fix. By the way I notice this commented out code which seems to be relevant:
#if 0 /* * The file descriptor must be dup'ed so that the standard * stdin/stdout/stderr are not closed. */
...
Marc